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_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']
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 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
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']
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']
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 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
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, ])
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
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'))
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'
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
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', '')
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'))
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)
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 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', '')
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)
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'))
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'
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 _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()
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()
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
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
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!')
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'))
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