Skip to content

Commit 3a07455

Browse files
robodooangv-odoo
authored andcommitted
[IMP] survey: enable custom speed rewards
This PR ams to improve speed reward logic in the survey. Users will now have the possibility to specify a default time limit, as well as custom time limits on each question. To keep things simple, the time limit on the question is used for both the "real" limit and the speed-related part of the score, both in the live session setting only. Modifying the time limit set on the survey should update all questions that are not customized. Here is an example of the desired behavior: (See `test_survey_time_limits_config`) 1. A time limit is set to 30s on a survey where no time configuration was done before => All questions are now rewarded with extra point after 30s. 2. After the previous step, question `A` 's time limit is overridden to 60s. Only this question will have 60s. (a flag for this override is also set). 3. Question `B`'s time limit is set to 20 sec, the same as above occurs. 4. Question `C` is set to "no time limit" (also an override). 4. At this point, the time limit at the survey level is reduced from 30 to 20s. This will make `B` not overridden anymore, while * A is still at 60s * C is still not limited (and no time-related rewards) See technical details in the individual commits. Task-2803327 closes odoo#115141 Related: odoo/enterprise#56810 Related: odoo/upgrade#5457 Signed-off-by: Thibault Delavallee (tde) <[email protected]> Co-authored-by: Andro Gvivradze <[email protected]>
2 parents 5317d72 + 17c1ef6 commit 3a07455

File tree

10 files changed

+571
-95
lines changed

10 files changed

+571
-95
lines changed

addons/survey/__manifest__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# Part of Odoo. See LICENSE file for full copyright and licensing details.
33
{
44
'name': 'Surveys',
5-
'version': '3.6',
5+
'version': '3.7',
66
'category': 'Marketing/Surveys',
77
'description': """
88
Create beautiful surveys and visualize answers

addons/survey/models/survey_question.py

Lines changed: 53 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,17 @@ class SurveyQuestion(models.Model):
4747
_rec_name = 'title'
4848
_order = 'sequence,id'
4949

50+
@api.model
51+
def default_get(self, fields_list):
52+
res = super().default_get(fields_list)
53+
if default_survey_id := self.env.context.get('default_survey_id'):
54+
survey = self.env['survey.survey'].browse(default_survey_id)
55+
if 'is_time_limited' in fields_list and 'is_time_limited' not in res:
56+
res['is_time_limited'] = survey.session_speed_rating
57+
if 'time_limit' in fields_list and 'time_limit' not in res:
58+
res['time_limit'] = survey.session_speed_rating_time_limit
59+
return res
60+
5061
# question generic data
5162
title = fields.Char('Title', required=True, translate=True)
5263
description = fields.Html(
@@ -58,6 +69,7 @@ class SurveyQuestion(models.Model):
5869
survey_id = fields.Many2one('survey.survey', string='Survey', ondelete='cascade')
5970
scoring_type = fields.Selection(related='survey_id.scoring_type', string='Scoring Type', readonly=True)
6071
sequence = fields.Integer('Sequence', default=10)
72+
session_available = fields.Boolean(related='survey_id.session_available', string='Live Session available', readonly=True)
6173
# page specific
6274
is_page = fields.Boolean('Is a page?')
6375
question_ids = fields.One2many('survey.question', string='Questions', compute="_compute_question_ids")
@@ -118,6 +130,7 @@ class SurveyQuestion(models.Model):
118130
# -- display & timing options
119131
is_time_limited = fields.Boolean("The question is limited in time",
120132
help="Currently only supported for live sessions.")
133+
is_time_customized = fields.Boolean("Customized speed rewards")
121134
time_limit = fields.Integer("Time limit (seconds)")
122135
# -- comments (simple choice, multiple choice, matrix (without count as an answer))
123136
comments_allowed = fields.Boolean('Show Comments Field')
@@ -179,6 +192,8 @@ class SurveyQuestion(models.Model):
179192
'All "Is a scored question = True" and "Question Type: Date" questions need an answer'),
180193
('scale', "CHECK (question_type != 'scale' OR (scale_min >= 0 AND scale_max <= 10 AND scale_min < scale_max))",
181194
'The scale must be a growing non-empty range between 0 and 10 (inclusive)'),
195+
('is_time_limited_have_time_limit', "CHECK (is_time_limited != TRUE OR time_limit IS NOT NULL AND time_limit > 0)",
196+
'All time-limited questions need a positive time limit'),
182197
]
183198

184199
# -------------------------------------------------------------------------
@@ -388,9 +403,14 @@ def copy(self, default=None):
388403
new_question.triggering_answer_ids = old_question.triggering_answer_ids
389404
return new_questions
390405

391-
# ------------------------------------------------------------
392-
# CRUD
393-
# ------------------------------------------------------------
406+
def create(self, vals_list):
407+
questions = super().create(vals_list)
408+
questions.filtered(
409+
lambda q: q.survey_id
410+
and (q.survey_id.session_speed_rating != q.is_time_limited
411+
or q.is_time_limited and q.survey_id.session_speed_rating_time_limit != q.time_limit)
412+
).is_time_customized = True
413+
return questions
394414

395415
@api.ondelete(at_uninstall=False)
396416
def _unlink_except_live_sessions_in_progress(self):
@@ -520,6 +540,36 @@ def _index(self):
520540
self.ensure_one()
521541
return list(self.survey_id.question_and_page_ids).index(self)
522542

543+
# ------------------------------------------------------------
544+
# SPEED RATING
545+
# ------------------------------------------------------------
546+
547+
def _update_time_limit_from_survey(self, is_time_limited=None, time_limit=None):
548+
"""Update the speed rating values after a change in survey's speed rating configuration.
549+
550+
* Questions that were not customized will take the new default values from the survey
551+
* Questions that were customized will not change their values, but this method will check
552+
and update the `is_time_customized` flag if necessary (to `False`) such that the user
553+
won't need to "actively" do it to make the question sensitive to change in survey values.
554+
555+
This is not done with `_compute`s because `is_time_limited` (and `time_limit`) would depend
556+
on `is_time_customized` and vice versa.
557+
"""
558+
write_vals = {}
559+
if is_time_limited is not None:
560+
write_vals['is_time_limited'] = is_time_limited
561+
if time_limit is not None:
562+
write_vals['time_limit'] = time_limit
563+
non_time_customized_questions = self.filtered(lambda s: not s.is_time_customized)
564+
non_time_customized_questions.write(write_vals)
565+
566+
# Reset `is_time_customized` as necessary
567+
customized_questions = self - non_time_customized_questions
568+
back_to_default_questions = customized_questions.filtered(
569+
lambda q: q.is_time_limited == q.survey_id.session_speed_rating
570+
and (q.is_time_limited is False or q.time_limit == q.survey_id.session_speed_rating_time_limit))
571+
back_to_default_questions.is_time_customized = False
572+
523573
# ------------------------------------------------------------
524574
# STATISTICS / REPORTING
525575
# ------------------------------------------------------------

0 commit comments

Comments
 (0)