コード例 #1
0
 def test_update_question_order_page(self):
     listing_form = ListingTemplate.objects.create(name='l12', description='desc1')
     kwargs = {'name': 'survey11', 'description': 'survey description demo12',
                       'has_sampling': True, 'sample_size': 10,'listing_form_id':listing_form.id}
     survey_obj = Survey.objects.create(**kwargs)
     batch_obj = Batch.objects.create(name='b1',description='d1', survey=survey_obj)
     qset = QuestionSet.get(id=batch_obj.id)
     question1 = mommy.make(Question, qset=qset, answer_type=NumericalAnswer.choice_name())
     QuestionOption.objects.create(
         question=question1,
         order=1,
         text="q7"
         ) 
     question2 = mommy.make(Question, qset=qset, answer_type=NumericalAnswer.choice_name())
     QuestionOption.objects.create(
         question=question1,
         order=4,
         text="q4"
         )
     QuestionFlow.objects.create(
         name = 'a1',
         desc = 'descq',
         question = question2,
         question_type = TextAnswer.choice_name(),
         next_question = question1,
         next_question_type = TextAnswer.choice_name()
         )
     QuestionLoop.objects.create(
         loop_starter = question2,
         loop_ender = question1
         )
     
     url = reverse('update_question_order_page', kwargs={"batch_id" : batch_obj.id})
     response = self.client.post(url,data={"order_information": [batch_obj.id]})
     self.assertIn(response.status_code, [200, 302])
コード例 #2
0
 def test_prep_values(self):
     # test base answer. For base answer just return value and text values
     answer = 'Test1'
     self.assertEquals(Answer.prep_value(answer).lower(), answer.lower())
     self.assertEquals(Answer.prep_text(answer).lower(), answer.lower())
     # test numerial answer. Confirm zfill normalization
     answer = 1
     self.assertEquals(NumericalAnswer.prep_text(answer), str(answer).zfill(NumericalAnswer.STRING_FILL_LENGTH))
     self.assertEquals(NumericalAnswer.prep_value(answer), str(answer).zfill(NumericalAnswer.STRING_FILL_LENGTH))
     # Confirm the auto response verbose_name (sorry I'm just throwing it in here)'
     self.assertEquals(AutoResponse.choice_name(), 'Auto Generated')
コード例 #3
0
 def test_answers_unicode_rep(self):
     self._create_ussd_non_group_questions()
     n_question = Question.objects.filter(
         answer_type=NumericalAnswer.choice_name()).first()
     answer = NumericalAnswer.create(self.interview, n_question, 1)
     self.assertEquals(str(answer.as_text), unicode(answer))
     # test update (since numeric makes use of thr parent implementation)
     answer.update(2)
     self.assertEquals(answer.as_value, 2)
     # just test to label also :)
     self.assertEquals(answer.to_label(), 2)
     #test to pretty_print
     self.assertEquals(str(answer.pretty_print()), '2')
コード例 #4
0
 def test_skip_logic_selection_in_form_question_creates_skip_flow(self):
     '''
     :return:
     '''
     q1 = Question.objects.create(qset_id=self.qset.id, response_validation_id=1,identifier='test1',text='test1', answer_type=NumericalAnswer.choice_name())
     q2 = Question.objects.create(qset_id=self.qset.id, response_validation_id=1,
                                  identifier='test2',
                                  text='test2', answer_type=NumericalAnswer.choice_name())
     q3 = Question.objects.create(qset_id=self.qset.id, response_validation_id=1,
                                  identifier='test3',
                                  text='test3', answer_type=NumericalAnswer.choice_name())
     q4 = Question.objects.create(qset_id=self.qset.id, response_validation_id=1,
                                  identifier='test4',
                                  text='test4', answer_type=NumericalAnswer.choice_name())
     q5 = Question.objects.create(qset_id=self.qset.id, response_validation_id=1,
                                  identifier='test5',
                                  text='test5', answer_type=NumericalAnswer.choice_name())
     test_condition = NumericalAnswer.validators()[0].__name__
     test_param = '15'
     form_data = {
         'action': LogicForm.SKIP_TO,
         'next_question': q4.pk,
         'condition': test_condition,
         'value': test_param
     }
     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)
     l = LogicForm(q1, 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=q1.id, next_question_id=q4.id)
             TextArgument.objects.get(flow=qf, param=test_param)
             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.assertTrue(False, 'Invalid form %s' % l.errors)
コード例 #5
0
 def test_prep_values(self):
     # test base answer. For base answer just return value and text values
     answer = 'Test1'
     self.assertEquals(Answer.prep_value(answer).lower(), answer.lower())
     self.assertEquals(Answer.prep_text(answer).lower(), answer.lower())
     # test numerial answer. Confirm zfill normalization
     answer = 1
     self.assertEquals(
         NumericalAnswer.prep_text(answer),
         str(answer).zfill(NumericalAnswer.STRING_FILL_LENGTH))
     self.assertEquals(
         NumericalAnswer.prep_value(answer),
         str(answer).zfill(NumericalAnswer.STRING_FILL_LENGTH))
     # Confirm the auto response verbose_name (sorry I'm just throwing it in here)'
     self.assertEquals(AutoResponse.choice_name(), 'Auto Generated')
コード例 #6
0
 def setUp(self):
     self.client = Client()
     user_without_permission = User.objects.create_user(
         username='******', email='*****@*****.**', password='******')
     raj = self.assign_permission_to(
         User.objects.create_user('demo12', '*****@*****.**', 'demo12'),
         'can_view_batches')
     self.listing_form = mommy.make(ListingTemplate)
     question1 = mommy.make(Question,
                            qset=self.listing_form,
                            answer_type=NumericalAnswer.choice_name())
     question2 = mommy.make(Question,
                            qset=self.listing_form,
                            answer_type=TextAnswer.choice_name())
     question3 = mommy.make(Question,
                            qset=self.listing_form,
                            answer_type=VideoAnswer.choice_name())
     self.client.login(username='******', password='******')
     self.form_data = {
         'name':
         'survey demo12',
         'description':
         'survey description demo12',
         'has_sampling':
         True,
         'sample_size':
         10,
         'random_sample_label':
         'q1 {{%s}} q2: {{%s}}' %
         (question1.identifier, question2.identifier)
     }
コード例 #7
0
 def _test_create_indicator_variable(self, **kwargs):
     self._create_ussd_non_group_questions()
     data = self.variable_data.copy()
     data.update(kwargs)
     numeric_question = Question.objects.filter(
         answer_type=NumericalAnswer.choice_name(),
         qset__id=self.qset.id).last()
     data['test_question'] = numeric_question.id
     url = reverse('add_variable')
     response = self.client.get(url)
     self.assertTrue(response.status_code, 200)
     self.assertIn('indicator/indicator_variable.html',
                   [t.name for t in response.templates])
     IndicatorVariable.objects.all().delete()
     variable_count = IndicatorVariable.objects.count()
     # now post to create
     response = self.client.post(url, data=data)
     self.assertIn(response.status_code, [200, 302])
     self.assertEquals(IndicatorVariable.objects.count(),
                       variable_count + 1)
     data['name'] = 'variablesd2'
     data['max'] = '1000'
     data['min'] = '0'
     variable_count = IndicatorVariable.objects.count()
     response = self.client.post(url, data=data)
     self.assertIn(response.status_code, [200, 302])
     self.assertEquals(IndicatorVariable.objects.count(),
                       variable_count + 1)
コード例 #8
0
ファイル: logic.py プロジェクト: unicefuganda/uSurvey
 def __init__(self, loop_starter, initial=None, *args, **kwargs):
     super(LoopingForm, self).__init__(initial=initial, *args, **kwargs)
     self.fields['loop_starter'].widget = forms.HiddenInput()
     self.fields['loop_starter'].initial = loop_starter.pk
     self.fields['loop_ender'].label = 'Loop Ends At:'
     empty = [('', '---------')]
     self.fields['loop_ender'].choices = empty + \
         [(q.pk, str(q)) for q in loop_starter.upcoming_flow_questions()]
     self.fields['previous_numeric_values'] = forms.ModelChoiceField(
         queryset=Question.objects.filter(pk__in=[
             q.pk for q in loop_starter.previous_inlines()
             if q.answer_type == NumericalAnswer.choice_name()
         ]))
     self.fields['previous_numeric_values'].empty_label = 'Code - Question'
     if self.instance:
         prev_question_count = getattr(self.instance,
                                       PreviousAnswerCount.choice_name(),
                                       None)
         fixed_count = getattr(self.instance, FixedLoopCount.choice_name(),
                               None)
         if prev_question_count:
             self.fields[
                 'previous_numeric_values'].initial = prev_question_count.value.pk
         if fixed_count:
             self.fields['repeat_count'].initial = fixed_count.value
     # self.fields['previous_numeric_values'].widget = forms.
     # self.fields['repeat_count'].widget = forms.TextInput(attrs={'disabled': 'disabled'})
     self.fields['previous_numeric_values'].required = False
     self.order_fields([
         'loop_starter', 'loop_label', 'repeat_logic',
         'previous_numeric_values', 'repeat_count', 'loop_ender'
     ])
コード例 #9
0
 def test_last_question_is_updated_after_response(self):
     self._create_ussd_non_group_questions(self.qset)
     interview = self.interview
     first_question = interview.question_set.start_question
     # confirm if its the Numerical answer
     self.assertEquals(first_question.answer_type, NumericalAnswer.choice_name())
     response = interview.respond()
     interview.refresh_from_db()
     self.assertEquals(interview.has_started, True)
     self.assertEquals(interview.last_question.id, first_question.id)
コード例 #10
0
 def test_last_question_is_updated_after_response(self):
     self._create_ussd_non_group_questions(self.qset)
     interview = self.interview
     first_question = interview.question_set.start_question
     # confirm if its the Numerical answer
     self.assertEquals(first_question.answer_type,
                       NumericalAnswer.choice_name())
     response = interview.respond()
     interview.refresh_from_db()
     self.assertEquals(interview.has_started, True)
     self.assertEquals(interview.last_question.id, first_question.id)
コード例 #11
0
 def test_question_text_is_given_when_no_response_is_supplied(self):
     self._create_ussd_non_group_questions(self.qset)
     interview = self.interview
     first_question = interview.question_set.start_question
     # confirm if its the Numerical answer
     self.assertEquals(first_question.answer_type, NumericalAnswer.choice_name())
     # interview has not started
     self.assertEquals(interview.has_started, False)
     self.assertEquals(Answer.objects.count(), 0)
     response = interview.respond()      # first question is numerical
     self.assertEquals(response, first_question.text)
コード例 #12
0
 def test_question_text_is_given_when_no_response_is_supplied(self):
     self._create_ussd_non_group_questions(self.qset)
     interview = self.interview
     first_question = interview.question_set.start_question
     # confirm if its the Numerical answer
     self.assertEquals(first_question.answer_type,
                       NumericalAnswer.choice_name())
     # interview has not started
     self.assertEquals(interview.has_started, False)
     self.assertEquals(Answer.objects.count(), 0)
     response = interview.respond()  # first question is numerical
     self.assertEquals(response, first_question.text)
コード例 #13
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])
コード例 #14
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'))
コード例 #15
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)
コード例 #16
0
 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))
コード例 #17
0
 def setUp(self):
     self.client = Client()
     user_without_permission = User.objects.create_user(username='******', email='*****@*****.**',
                                                        password='******')
     raj = self.assign_permission_to(User.objects.create_user('demo12', '*****@*****.**', 'demo12'),
                                     'can_view_batches')
     self.listing_form = mommy.make(ListingTemplate)
     question1 = mommy.make(Question, qset=self.listing_form, answer_type=NumericalAnswer.choice_name())
     question2 = mommy.make(Question, qset=self.listing_form, answer_type=TextAnswer.choice_name())
     question3 = mommy.make(Question, qset=self.listing_form, answer_type=VideoAnswer.choice_name())
     self.client.login(username='******', password='******')
     self.form_data = {'name': 'survey demo12', 'description': 'survey description demo12',
                       'has_sampling': True, 'sample_size': 10,
                       'random_sample_label': 'q1 {{%s}} q2: {{%s}}' % (question1.identifier, question2.identifier)}
コード例 #18
0
 def test_odk_answer_methods(self):
     # test odk contain
     path = '/qset/qset1/surveyQuestions/q1'
     value = 'me doing somthing'
     self.assertEquals(Answer.odk_contains(path, value),
                       "regex(%s, '.*(%s).*')" % (path, value))
     self.assertEquals(Answer.odk_starts_with(path, value),
                       "regex(%s, '^(%s).*')" % (path, value))
     self.assertEquals(Answer.odk_ends_with(path, value),
                       "regex(%s, '.*(%s)$')" % (path, value))
     value = 4
     upperlmt = 10
     self.assertEquals(Answer.odk_greater_than(path, value),
                       "%s > '%s'" % (path, value))
     self.assertEquals(Answer.odk_less_than(path, value),
                       "%s < '%s'" % (path, value))
     self.assertEquals(
         Answer.odk_between(path, value, upperlmt),
         "(%s > '%s') and (%s <= '%s')" %
         (path, value, path, upperlmt))
     self.assertEquals(NumericalAnswer.odk_less_than(path, value),
                       "%s < %s" % (path, value))
     self.assertEquals(
         NumericalAnswer.odk_between(path, value, upperlmt),
         "(%s > %s) and (%s <= %s)" % (path, value, path, upperlmt))
     value = '20-07-2017'
     self.assertEquals(DateAnswer.odk_greater_than(path, value),
                       "%s > %s" % (path, DateAnswer.to_odk_date(value)))
     self.assertEquals(DateAnswer.odk_less_than(path, value),
                       "%s < %s" % (path, DateAnswer.to_odk_date(value)))
     upperlmt = '25-08-2017'
     self.assertEquals(
         DateAnswer.odk_between(path, value, upperlmt),
         "(%s > %s) and (%s <= %s)" %
         (path, DateAnswer.to_odk_date(value), path,
          DateAnswer.to_odk_date(upperlmt)))
コード例 #19
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))
コード例 #20
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()
コード例 #21
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()
コード例 #22
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))
コード例 #23
0
 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))
コード例 #24
0
 def _test_create_indicator_variable(self, **kwargs):
     self._create_ussd_non_group_questions()
     data = self.variable_data.copy()
     data.update(kwargs)
     numeric_question = Question.objects.filter(answer_type=NumericalAnswer.choice_name(),
                                                qset__id=self.qset.id).first()
     data['test_question'] = numeric_question.id
     url = reverse('add_variable')
     response = self.client.get(url)
     self.assertTrue(response.status_code, 200)
     self.assertIn('indicator/indicator_variable.html', [t.name for t in response.templates])
     IndicatorVariable.objects.all().delete()
     variable_count = IndicatorVariable.objects.count()
     # now post to create
     response = self.client.post(url, data=data)
     self.assertIn(response.status_code, [200, 302])
     self.assertEquals(IndicatorVariable.objects.count(), variable_count+1)
     data['name'] = 'variable2'
     data['max'] = '1000'
     data['min'] = '0'
     variable_count = IndicatorVariable.objects.count()
     response = self.client.post(url, data=data)
     self.assertIn(response.status_code, [200, 302])
     self.assertEquals(IndicatorVariable.objects.count(), variable_count + 1)
コード例 #25
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)
コード例 #26
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)
コード例 #27
0
 def test_skip_logic_selection_in_form_question_creates_skip_flow(self):
     '''
     :return:
     '''
     q1 = Question.objects.create(qset_id=self.qset.id,
                                  response_validation_id=1,
                                  identifier='test1',
                                  text='test1',
                                  answer_type=NumericalAnswer.choice_name())
     q2 = Question.objects.create(qset_id=self.qset.id,
                                  response_validation_id=1,
                                  identifier='test2',
                                  text='test2',
                                  answer_type=NumericalAnswer.choice_name())
     q3 = Question.objects.create(qset_id=self.qset.id,
                                  response_validation_id=1,
                                  identifier='test3',
                                  text='test3',
                                  answer_type=NumericalAnswer.choice_name())
     q4 = Question.objects.create(qset_id=self.qset.id,
                                  response_validation_id=1,
                                  identifier='test4',
                                  text='test4',
                                  answer_type=NumericalAnswer.choice_name())
     q5 = Question.objects.create(qset_id=self.qset.id,
                                  response_validation_id=1,
                                  identifier='test5',
                                  text='test5',
                                  answer_type=NumericalAnswer.choice_name())
     test_condition = NumericalAnswer.validators()[0].__name__
     test_param = '15'
     form_data = {
         'action': LogicForm.SKIP_TO,
         'next_question': q4.pk,
         'condition': test_condition,
         'value': test_param
     }
     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)
     l = LogicForm(q1, 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=q1.id,
                                           next_question_id=q4.id)
             TextArgument.objects.get(flow=qf, param=test_param)
             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.assertTrue(False, 'Invalid form %s' % l.errors)
コード例 #28
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!')
コード例 #29
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())
コード例 #30
0
 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)
コード例 #31
0
    class QuestionForm(ModelForm, FormOrderMixin):
        VALIDATION_ANSWER_TYPES = [DateAnswer.choice_name(), TextAnswer.choice_name(),
                                   NumericalAnswer.choice_name(), AutoResponse.choice_name()]
        options = forms.CharField(max_length=50, widget=forms.HiddenInput(), required=False)
        response_validation = ValidationField(queryset=ResponseValidation.objects.all(), required=False)

        def __init__(
                self,
                qset,
                data=None,
                initial=None,
                parent_question=None,
                instance=None,
                prev_question=None):
            super(QuestionForm, self).__init__(
                data=data, initial=initial, instance=instance)
            self.fields['identifier'].label = "Variable name"
            self.fields['qset'].widget = forms.HiddenInput()
            self.fields['qset'].initial = qset.pk
            self.qset = qset
            self.prev_question = prev_question
            # depending on type of ussd/odk access of qset restrict the answer
            # type
            self.fields['answer_type'].choices = [
                choice for choice in self.fields['answer_type'].choices if choice[0] in qset.answer_types]
            self.fields['answer_type'].choices.insert(
                0, ('', '----Select Answer Type----'))
            if instance:
                self.help_text = ' and '.join(AnswerAccessDefinition.access_channels(instance.answer_type))
                self.fields['answer_type'].help_text = self.help_text
            self.answer_map = {}
            definitions = AnswerAccessDefinition.objects.all()
            for defi in definitions:
                self.answer_map[defi.answer_type] = self.answer_map.get(defi.answer_type, [])
                self.answer_map[defi.answer_type].append(defi.channel)
            self.fields['response_validation'].icons = {'add': {'data-toggle': "modal",
                                                                 'data-target': "#add_validation",
                                                                 'id': 'add_validation_button',
                                                                 'title': 'Add Validation'},
                                                        }
            self.parent_question = parent_question
            self.order_fields(['module', 'group', 'identifier',
                               'text', 'answer_type', 'mandatory'])

        class Meta:
            model = model_class
            exclude = []
            widgets = {
                'text': forms.Textarea(
                    attrs={
                        "rows": 5,
                        "cols": 30,
                        "maxlength": "150",
                    }),
            }

        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 clean_options(self):
            options = dict(self.data).get('options')
            if options:
                options = filter(lambda text: text.strip(), options)
                # options = map(lambda option: re.sub("[%s]" % settings.USSD_IGNORED_CHARACTERS, '', option), options)
                options = map(
                    lambda option: re.sub(
                        "  ", ' ', option), options)
                options = map(lambda option: option.strip(), options)
                self.cleaned_data['options'] = options
            return options

        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']

        def clean_text(self):
            """Make sure any field referenced here belongs to same batch. Field refs are denoted by {{.+}} brackets
            :return:
            """
            pattern = '{{ *([0-9a-zA-Z_]+) *}}'
            label = self.data.get('text', '')
            requested_identifiers = re.findall(pattern, label)
            if requested_identifiers:
                ids = self.qset.questions.filter(
                    identifier__in=requested_identifiers).values_list(
                    'identifier', flat=True)
                ids = list(ids)
                if len(set(ids)) != len(set(requested_identifiers)):
                    raise ValidationError(
                        '%s is not in %s' %
                        (', '.join(
                            set(requested_identifiers).difference(ids)),
                            self.qset.name))
            return self.cleaned_data['text']

        def clean(self):
            answer_type = self.cleaned_data.get('answer_type', None)
            options = self.cleaned_data.get('options', None)
            response_validation = self.cleaned_data.get('response_validation', None)
            text = self.cleaned_data.get('text', None)
            self._check__multichoice_and_options_compatibility(
                answer_type, options)
            self._strip_special_characters_for_ussd(text)
            if answer_type:
                answer_class = Answer.get_class(answer_type)
                validator_names = [validator.__name__ for validator in answer_class.validators()]
                if response_validation and response_validation.validation_test not in validator_names:
                    raise ValidationError('Selected Validation is not compatible with chosen answer type')
            return self.cleaned_data

        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 _strip_special_characters_for_ussd(self, text):
            if text:
                text = re.sub(
                    "[%s]" %
                    settings.USSD_IGNORED_CHARACTERS,
                    '',
                    text)
                self.cleaned_data['text'] = re.sub("  ", ' ', text)

        def kwargs_has_batch(self, **kwargs):
            return 'qset' in kwargs and isinstance(kwargs['qset'], Batch)

        def options_supplied(self, commit):
            return commit and self.cleaned_data.get('options', None)

        def save_question_options(self, question):
            order = 0
            options = self.cleaned_data['options']
            question.options.all().delete()
            # options.sort()
            for text in options:
                order += 1
                QuestionOption.objects.create(
                    question=question, text=text, order=order)

        def save(self, commit=True, zombie=False, **kwargs):
            question = super(QuestionForm, self).save(commit=False)
            qset = question.qset
            if commit:
                if question.pk is None:
                    question.save()
                    # get the last question inline
                    # create a inline flow with current qset
                    qset = question.qset
                    # qset = QuestionSet.get(id=qset.id)
                    if self.prev_question:
                        last_question = self.prev_question
                    else:
                        last_question = qset.last_question_inline()
                    if last_question:
                        if zombie is False:
                            # incase, inline flow with no next quest already
                            # exists
                            flow, _ = QuestionFlow.objects.get_or_create(
                                question=last_question, validation__isnull=True)
                            prev_next_question = flow.next_question
                            flow.next_question = question
                            flow.save()
                            # now connect present question back to the flow
                            QuestionFlow.objects.create(
                                question=question, next_question=prev_next_question)
                    elif qset.start_question is None:
                        qset.start_question = question
                        qset.save()
                else:
                    question.save()
                if hasattr(qset, 'survey'):     # basicallyy check for Batch scenario
                    SurveyParameterList.update_parameter_list(qset)

                # self.qset.questions_inline.invalidate()
            if self.options_supplied(commit):
                self.save_question_options(question)
            return question
コード例 #32
0
ファイル: logic.py プロジェクト: unicefuganda/uSurvey
 def __init__(self, loop_starter, initial=None, *args, **kwargs):
     super(LoopingForm, self).__init__(initial=initial, *args, **kwargs)
     self.fields['loop_starter'].widget = forms.HiddenInput()
     self.fields['loop_starter'].initial = loop_starter.pk
     self.fields['loop_ender'].label = 'Loop Ends At:'
     empty = [('', '---------')]
     self.fields['loop_ender'].choices = empty + \
         [(q.pk, str(q)) for q in loop_starter.upcoming_flow_questions()]
     self.fields['previous_numeric_values'] = forms.ModelChoiceField(queryset=Question.objects.filter(
         pk__in=[q.pk for q in loop_starter.previous_inlines() if q.answer_type == NumericalAnswer.choice_name()]
     ))
     self.fields['previous_numeric_values'].empty_label = 'Code - Question'
     if self.instance:
         prev_question_count = getattr(
             self.instance, PreviousAnswerCount.choice_name(), None)
         fixed_count = getattr(
             self.instance, FixedLoopCount.choice_name(), None)
         if prev_question_count:
             self.fields['previous_numeric_values'].initial = prev_question_count.value.pk
         if fixed_count:
             self.fields['repeat_count'].initial = fixed_count.value
     # self.fields['previous_numeric_values'].widget = forms.
     # self.fields['repeat_count'].widget = forms.TextInput(attrs={'disabled': 'disabled'})
     self.fields['previous_numeric_values'].required = False
     self.order_fields(['loop_starter',
                        'loop_label',
                        'repeat_logic',
                        'previous_numeric_values',
                        'repeat_count',
                        'loop_ender'])