diff --git a/addons/website_slides/models/slide_question.py b/addons/website_slides/models/slide_question.py index 27e4f43ae7d..a092b1a874d 100644 --- a/addons/website_slides/models/slide_question.py +++ b/addons/website_slides/models/slide_question.py @@ -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') diff --git a/addons/website_slides/tests/__init__.py b/addons/website_slides/tests/__init__.py index 60ce510cb5c..57634fa98f1 100644 --- a/addons/website_slides/tests/__init__.py +++ b/addons/website_slides/tests/__init__.py @@ -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 diff --git a/addons/website_slides/tests/test_slide_question.py b/addons/website_slides/tests/test_slide_question.py new file mode 100644 index 00000000000..13beaa97034 --- /dev/null +++ b/addons/website_slides/tests/test_slide_question.py @@ -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) diff --git a/addons/website_slides/views/slide_question_views.xml b/addons/website_slides/views/slide_question_views.xml index 8be329f5b58..0b3d9fb7962 100644 --- a/addons/website_slides/views/slide_question_views.xml +++ b/addons/website_slides/views/slide_question_views.xml @@ -5,6 +5,12 @@ slide.question
+
+