def __init__(self, *args, contribution, questionnaire, **kwargs): super().__init__(*args, **kwargs) self.questionnaire = questionnaire for question in self.questionnaire.questions.all(): if question.is_text_question: field = TextAnswerField(label=question.text) elif question.is_rating_question: field = RatingAnswerField( widget_choices=CHOICES[question.type], choices=zip(CHOICES[question.type].values, CHOICES[question.type].names), label=question.text, allows_textanswer=question.allows_additional_textanswers, ) elif question.is_heading_question: field = HeadingField(label=question.text) identifier = answer_field_id(contribution, questionnaire, question) self.fields[identifier] = field if question.is_rating_question and question.allows_additional_textanswers: textanswer_field = TextAnswerField( label=question.text, related_answer_field_id=identifier) textanswer_identifier = answer_field_id( contribution, questionnaire, question, additional_textanswer=True) self.fields[textanswer_identifier] = textanswer_field
def let_user_vote_for_evaluation(app, user, evaluation): url = "/student/vote/{}".format(evaluation.id) page = app.get(url, user=user, status=200) form = page.forms["student-vote-form"] for contribution in evaluation.contributions.all().prefetch_related( "questionnaires", "questionnaires__questions"): for questionnaire in contribution.questionnaires.all(): for question in questionnaire.questions.all(): if question.is_text_question: form[answer_field_id(contribution, questionnaire, question)] = "Lorem ispum" elif question.is_rating_question: form[answer_field_id(contribution, questionnaire, question)] = 1 form.submit()
def test_xmin_of_all_answers_is_updated(self): page = self.app.get(self.url, user=self.voting_user1) form = page.forms["student-vote-form"] self.fill_form(form) form.submit() page = self.app.get(self.url, user=self.voting_user2) form = page.forms["student-vote-form"] self.fill_form(form) form[answer_field_id(self.evaluation.general_contribution, self.top_general_questionnaire, self.top_grade_question)] = 2 form.submit() self.assertEqual( set(Answer.__subclasses__()), {RatingAnswerCounter, TextAnswer}, "This test requires an update if a new answer type is added. Also, when adding a new answer type, " "the new table should probably also be vacuumed and clustered -- see and update " "https://github.com/e-valuation/EvaP/wiki/Installation#database-vacuuming-and-clustering", ) query = RatingAnswerCounter.objects.raw( "SELECT id, xmin FROM evaluation_ratinganswercounter") rating_answer_xmins = [row.xmin for row in query] self.assertTrue( all(xmin == rating_answer_xmins[0] for xmin in rating_answer_xmins)) query = TextAnswer.objects.raw( "SELECT id, xmin FROM evaluation_textanswer") text_answer_xmins = [row.xmin for row in query] self.assertTrue( all(xmin == text_answer_xmins[0] for xmin in text_answer_xmins))
def __init__(self, *args, contribution, questionnaire, **kwargs): super().__init__(*args, **kwargs) self.questionnaire = questionnaire for question in self.questionnaire.questions.all(): if question.is_text_question: field = TextAnswerField.from_question(question) elif question.is_rating_question: field = RatingAnswerField.from_question(question) elif question.is_heading_question: field = HeadingField.from_question(question) identifier = answer_field_id(contribution, questionnaire, question) self.fields[identifier] = field if question.is_rating_question and question.allows_additional_textanswers: textanswer_field = TextAnswerField( label=question.text, related_answer_field_id=identifier) textanswer_identifier = answer_field_id( contribution, questionnaire, question, additional_textanswer=True) self.fields[textanswer_identifier] = textanswer_field
def fill_form(self, form, fill_general_complete=True, fill_contributors_complete=True): contribution = self.evaluation.general_contribution questionnaire = self.top_general_questionnaire form[answer_field_id(contribution, questionnaire, self.top_text_question)] = "some text" form[answer_field_id(contribution, questionnaire, self.top_grade_question)] = 3 form[answer_field_id(contribution, questionnaire, self.top_likert_question)] = 1 form[answer_field_id( contribution, questionnaire, self.top_likert_question, additional_textanswer=True)] = "some additional text" questionnaire = self.bottom_general_questionnaire form[answer_field_id(contribution, questionnaire, self.bottom_text_question)] = "some bottom text" form[answer_field_id(contribution, questionnaire, self.bottom_grade_question)] = 4 if fill_general_complete: form[answer_field_id(contribution, questionnaire, self.bottom_likert_question)] = 2 contribution = self.contribution1 questionnaire = self.contributor_questionnaire form[answer_field_id( contribution, questionnaire, self.contributor_text_question)] = "some other text" form[answer_field_id(contribution, questionnaire, self.contributor_likert_question)] = 4 form[answer_field_id( contribution, questionnaire, self.contributor_likert_question, additional_textanswer=True)] = "some other additional text" contribution = self.contribution2 form[answer_field_id( contribution, questionnaire, self.contributor_text_question)] = "some more text" if fill_contributors_complete: form[answer_field_id(contribution, questionnaire, self.contributor_likert_question)] = 2
def vote(request, evaluation_id): # pylint: disable=too-many-nested-blocks,too-many-branches evaluation = get_object_or_404(Evaluation, id=evaluation_id) if not evaluation.can_be_voted_for_by(request.user): raise PermissionDenied form_groups = get_vote_page_form_groups(request, evaluation, preview=False) if not all(form.is_valid() for form_group in form_groups.values() for form in form_group): return render_vote_page(request, evaluation, preview=False) # all forms are valid, begin vote operation with transaction.atomic(): # add user to evaluation.voters # not using evaluation.voters.add(request.user) since that fails silently when done twice. evaluation.voters.through.objects.create( userprofile_id=request.user.pk, evaluation_id=evaluation.pk) for contribution, form_group in form_groups.items(): for questionnaire_form in form_group: questionnaire = questionnaire_form.questionnaire for question in questionnaire.questions.all(): if question.is_heading_question: continue identifier = answer_field_id(contribution, questionnaire, question) value = questionnaire_form.cleaned_data.get(identifier) if question.is_text_question: if value: question.answer_class.objects.create( contribution=contribution, question=question, answer=value) else: if value != NO_ANSWER: answer_counter, __ = question.answer_class.objects.get_or_create( contribution=contribution, question=question, answer=value) answer_counter.count += 1 answer_counter.save() if question.allows_additional_textanswers: textanswer_identifier = answer_field_id( contribution, questionnaire, question, additional_textanswer=True) textanswer_value = questionnaire_form.cleaned_data.get( textanswer_identifier) if textanswer_value: TextAnswer.objects.create( contribution=contribution, question=question, answer=textanswer_value) # Update all answer rows to make sure no system columns give away which one was last modified # see https://github.com/e-valuation/EvaP/issues/1384 RatingAnswerCounter.objects.filter( contribution__evaluation=evaluation).update(id=F("id")) TextAnswer.objects.filter(contribution__evaluation=evaluation).update( id=F("id")) if not evaluation.can_publish_text_results: # enable text result publishing if first user confirmed that publishing is okay or second user voted if (request.POST.get("text_results_publish_confirmation_top") == "on" or request.POST.get( "text_results_publish_confirmation_bottom") == "on" or evaluation.voters.count() >= 2): evaluation.can_publish_text_results = True evaluation.save() evaluation.evaluation_evaluated.send( sender=Evaluation, request=request, semester=evaluation.course.semester) messages.success(request, _("Your vote was recorded.")) return HttpResponse(SUCCESS_MAGIC_STRING)