[IMP] website_slides: allow multiple correct answers

Purpose
=======
Currently the user interface let you specify several correct answers
per quiz question. But when you save the course, you get a notification
error. As those are simple quizzes, it might be interesting to simply
allow multiple answers.

Specifications
==============
Allow questions with multiple correct answers.
Back-end views: improve feedback when user forget to set at least one correct
answer and one incorrect answer per question.

Task-3366803

closes odoo/odoo#127065

Signed-off-by: Stéphane Debauche (std) <std@odoo.com>
This commit is contained in:
Lopes Marc (loma)
2023-08-23 14:43:06 +02:00
parent 122ff3ca59
commit bb4755f979
4 changed files with 63 additions and 6 deletions
+18 -6
View File
@@ -15,6 +15,7 @@ class SlideQuestion(models.Model):
question = fields.Char("Question Name", required=True, translate=True)
slide_id = fields.Many2one('slide.slide', string="Content", required=True, ondelete='cascade')
answer_ids = fields.One2many('slide.answer', 'question_id', string="Answer", copy=True)
answers_validation_error = fields.Char("Error on Answers", compute='_compute_answers_validation_error')
# statistics
attempts_count = fields.Integer(compute='_compute_statistics', groups='website_slides.group_website_slides_officer')
attempts_avg = fields.Float(compute="_compute_statistics", digits=(6, 2), groups='website_slides.group_website_slides_officer')
@@ -22,11 +23,15 @@ class SlideQuestion(models.Model):
@api.constrains('answer_ids')
def _check_answers_integrity(self):
for question in self:
if len(question.answer_ids.filtered(lambda answer: answer.is_correct)) != 1:
raise ValidationError(_('Question "%s" must have 1 correct answer', question.question))
if len(question.answer_ids) < 2:
raise ValidationError(_('Question "%s" must have 1 correct answer and at least 1 incorrect answer', question.question))
questions_to_fix = [
f'- {question.slide_id.name}: {question.question}'
for question in self
if question.answers_validation_error
]
if questions_to_fix:
raise ValidationError(_(
'All questions must have at least one correct answer and one incorrect answer: \n%s\n',
'\n'.join(questions_to_fix)))
@api.depends('slide_id')
def _compute_statistics(self):
@@ -45,12 +50,19 @@ class SlideQuestion(models.Model):
question.attempts_avg = stats.get('attempts_count', 0) / stats.get('attempts_unique', 1) if stats else 0
question.done_count = stats.get('done_count', 0) if stats else 0
@api.depends('answer_ids', 'answer_ids.is_correct')
def _compute_answers_validation_error(self):
for question in self:
correct = question.answer_ids.filtered('is_correct')
question.answers_validation_error = _(
'This question must have at least one correct answer and one incorrect answer.'
) if not correct or correct == question.answer_ids else ''
class SlideAnswer(models.Model):
_name = "slide.answer"
_rec_name = "text_value"
_description = "Slide Question's Answer"
_order = 'question_id, sequence'
_order = 'question_id, sequence, id'
sequence = fields.Integer("Sequence")
question_id = fields.Many2one('slide.question', string="Question", required=True, ondelete='cascade')
+1
View File
@@ -7,6 +7,7 @@ from . import test_embed_detection
from . import test_gamification_karma
from . import test_security
from . import test_slide_channel
from . import test_slide_question
from . import test_slide_resource
from . import test_slide_slide
from . import test_statistics
@@ -0,0 +1,38 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import Command
from odoo.addons.website_slides.tests import common as slides_common
from odoo.tests.common import users
class TestSlideQuestionManagement(slides_common.SlidesCase):
@users('user_officer')
def test_compute_answers_validation_error(self):
channel = self.env['slide.channel'].create({
'name': 'Test compute answers channel',
'slide_ids': [Command.create({
'name': "Test compute answers validation error slide",
'slide_category': 'quiz',
'question_ids': [Command.create({
'question': 'Will test compute answers validation error pass?',
'answer_ids': [
Command.create({
'text_value': 'An incorrect answer',
}),
Command.create({
'is_correct': True,
'text_value': 'A correct answer',
})
]
})]
})]
})
question = channel.slide_ids[0].question_ids[0]
self.assertFalse(question.answers_validation_error)
for val in (False, True):
question.answer_ids[0].is_correct = val
question.answer_ids[1].is_correct = val
self.assertTrue(question.answers_validation_error)
@@ -5,6 +5,12 @@
<field name="model">slide.question</field>
<field name="arch" type="xml">
<form string="Quiz">
<div invisible="answers_validation_error == ''">
<div class="alert alert-info my-1 mx-2" role="alert" aria-label="Validation error">
<i class="fa fa-info-circle" aria-hidden="true"/>
<field name="answers_validation_error" class="ms-2" readonly="1"/>
</div>
</div>
<sheet>
<label for="question" string="Question Name"/>
<h1>