[REF] survey: move from onchange to editable stored fields
PURPOSE Try to move from onchange / default_get to stored editable computed fields. Behavior should be the same (computed or set by user), with support of create / write / onchange field update without additional code. SPECIFICATIONS Update classic fields updated in some cases by onchange and/or default methods by fields with store=True, readonly=False. It means their value comes either from manual user input, either from trigger based computation. Remove onchange and default_get when possible, leading to an unique computation method and clearing fields definition. Also clean some fields definition inconsistencies, notably required fields that should instead be correctly computed or default that have no real meaning. SURVEY USE CASES - On survey.question, the question_type field should be emptied if the question is a page (is_page = True) - On survey.survey, if scoring is configured, the minimum scoring success should be between 0 and 100 (added SQL constraint). - On survey.survey, the certification field cannot be True if we're in no scoring mode (scoring_type = 'no_scoring') - On survey.survey, the attempts number cannot be limited (is_attempts_limited is False) if the access mode is public and the login is not required. - On survey.survey, we cannot give a badge (certification_give_badge is False) if it's not a certification or if the login is not required. - On survey.invite, the "subject" and "body" field are based on the template used (template_id field). MISC - As "validation_email" works with "validation_required", we removed the onchange on "validation_email". - To avoid extra complexity with an onchange on "is_time_limited" and "time_limit", we simply default the time_limit field to 10. LINKS Upgrade PR odoo/upgrade#847 Task 2187377 closes odoo/odoo#46291 Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||||
{
|
||||
'name': 'Surveys',
|
||||
'version': '3.1',
|
||||
'version': '3.2',
|
||||
'category': 'Marketing/Surveys',
|
||||
'description': """
|
||||
Create beautiful surveys and visualize answers
|
||||
|
||||
@@ -79,7 +79,8 @@ class SurveyQuestion(models.Model):
|
||||
('datetime', 'Datetime'),
|
||||
('simple_choice', 'Multiple choice: only one answer'),
|
||||
('multiple_choice', 'Multiple choice: multiple answers allowed'),
|
||||
('matrix', 'Matrix')], string='Question Type')
|
||||
('matrix', 'Matrix')], string='Question Type',
|
||||
compute='_compute_question_type', readonly=False, store=True)
|
||||
is_scored_question = fields.Boolean(
|
||||
'Scored', compute='_compute_is_scored_question',
|
||||
readonly=False, store=True, copy=True,
|
||||
@@ -170,15 +171,11 @@ class SurveyQuestion(models.Model):
|
||||
'All "Is a scored question = True" and "Question Type: Date" questions need an answer')
|
||||
]
|
||||
|
||||
@api.onchange('validation_email')
|
||||
def _onchange_validation_email(self):
|
||||
if self.validation_email:
|
||||
self.validation_required = False
|
||||
|
||||
@api.onchange('is_page')
|
||||
def _onchange_is_page(self):
|
||||
if self.is_page:
|
||||
self.question_type = False
|
||||
@api.depends('is_page')
|
||||
def _compute_question_type(self):
|
||||
for question in self:
|
||||
if not question.question_type or question.is_page:
|
||||
question.question_type = False
|
||||
|
||||
@api.depends('survey_id.question_and_page_ids.is_page', 'survey_id.question_and_page_ids.sequence')
|
||||
def _compute_question_ids(self):
|
||||
|
||||
@@ -106,9 +106,10 @@ class Survey(models.Model):
|
||||
compute="_compute_is_attempts_limited", store=True, readonly=False)
|
||||
attempts_limit = fields.Integer('Number of attempts', default=1)
|
||||
is_time_limited = fields.Boolean('The survey is limited in time')
|
||||
time_limit = fields.Float("Time limit (minutes)")
|
||||
time_limit = fields.Float("Time limit (minutes)", default=10)
|
||||
# certification
|
||||
certification = fields.Boolean('Is a Certification')
|
||||
certification = fields.Boolean('Is a Certification', compute='_compute_certification',
|
||||
readonly=False, store=True)
|
||||
certification_mail_template_id = fields.Many2one(
|
||||
'mail.template', 'Email Template',
|
||||
domain="[('model', '=', 'survey.user_input')]",
|
||||
@@ -126,7 +127,8 @@ class Survey(models.Model):
|
||||
# - If the certification badge is not set, show certification_badge_id and only display create option in the m2o
|
||||
# - If the certification badge is set, show certification_badge_id_dummy in 'no create' mode.
|
||||
# So it can be edited but not removed or replaced.
|
||||
certification_give_badge = fields.Boolean('Give Badge')
|
||||
certification_give_badge = fields.Boolean('Give Badge', compute='_compute_certification_give_badge',
|
||||
readonly=False, store=True)
|
||||
certification_badge_id = fields.Many2one('gamification.badge', 'Certification Badge')
|
||||
certification_badge_id_dummy = fields.Many2one(related='certification_badge_id', string='Certification Badge ')
|
||||
# live sessions
|
||||
@@ -157,6 +159,8 @@ class Survey(models.Model):
|
||||
('session_code_unique', 'unique(session_code)', 'Session code should be unique'),
|
||||
('certification_check', "CHECK( scoring_type!='no_scoring' OR certification=False )",
|
||||
'You can only create certifications for surveys that have a scoring mechanism.'),
|
||||
('scoring_success_min_check', "CHECK( scoring_success_min IS NULL OR (scoring_success_min>=0 AND scoring_success_min<=100) )",
|
||||
'The percentage of success has to be defined between 0 and 100.'),
|
||||
('time_limit_check', "CHECK( (is_time_limited=False) OR (time_limit is not null AND time_limit > 0) )",
|
||||
'The time limit needs to be a positive number if the survey is time limited.'),
|
||||
('attempts_limit_check', "CHECK( (is_attempts_limited=False) OR (attempts_limit is not null AND attempts_limit > 0) )",
|
||||
@@ -207,9 +211,9 @@ class Survey(models.Model):
|
||||
@api.depends('question_and_page_ids.is_conditional', 'users_login_required', 'access_mode')
|
||||
def _compute_is_attempts_limited(self):
|
||||
for survey in self:
|
||||
if any(question.is_conditional for question in survey.question_and_page_ids)\
|
||||
or (survey.access_mode == 'public' and not survey.users_login_required)\
|
||||
or survey.is_attempts_limited is None:
|
||||
if not survey.is_attempts_limited or \
|
||||
(survey.access_mode == 'public' and not survey.users_login_required) or \
|
||||
any(question.is_conditional for question in survey.question_and_page_ids):
|
||||
survey.is_attempts_limited = False
|
||||
|
||||
@api.depends('session_start_time', 'user_input_ids')
|
||||
@@ -276,36 +280,24 @@ class Survey(models.Model):
|
||||
for survey in self:
|
||||
survey.has_conditional_questions = any(question.is_conditional for question in survey.question_and_page_ids)
|
||||
|
||||
@api.onchange('scoring_success_min')
|
||||
def _onchange_scoring_success_min(self):
|
||||
if self.scoring_success_min < 0 or self.scoring_success_min > 100:
|
||||
self.scoring_success_min = 80.0
|
||||
@api.depends('scoring_type')
|
||||
def _compute_certification(self):
|
||||
for survey in self:
|
||||
if not survey.certification or survey.scoring_type == 'no_scoring':
|
||||
survey.certification = False
|
||||
|
||||
@api.onchange('scoring_type')
|
||||
def _onchange_scoring_type(self):
|
||||
if self.scoring_type == 'no_scoring':
|
||||
self.certification = False
|
||||
self.is_time_limited = False
|
||||
|
||||
@api.onchange('attempts_limit')
|
||||
def _onchange_attempts_limit(self):
|
||||
if self.attempts_limit <= 0:
|
||||
self.attempts_limit = 1
|
||||
|
||||
@api.onchange('is_time_limited', 'time_limit')
|
||||
def _onchange_time_limit(self):
|
||||
if self.is_time_limited and (not self.time_limit or self.time_limit <= 0):
|
||||
self.time_limit = 10
|
||||
@api.depends('users_login_required', 'certification')
|
||||
def _compute_certification_give_badge(self):
|
||||
for survey in self:
|
||||
if not survey.certification_give_badge or \
|
||||
not survey.users_login_required or \
|
||||
not survey.certification:
|
||||
survey.certification_give_badge = False
|
||||
|
||||
def _read_group_states(self, values, domain, order):
|
||||
selection = self.env['survey.survey'].fields_get(allfields=['state'])['state']['selection']
|
||||
return [s[0] for s in selection]
|
||||
|
||||
@api.onchange('users_login_required', 'certification')
|
||||
def _onchange_set_certification_give_badge(self):
|
||||
if not self.users_login_required or not self.certification:
|
||||
self.certification_give_badge = False
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# CRUD
|
||||
# ------------------------------------------------------------
|
||||
|
||||
@@ -28,8 +28,8 @@ class SurveyInvite(models.TransientModel):
|
||||
return self.env.user.partner_id
|
||||
|
||||
# composer content
|
||||
subject = fields.Char('Subject')
|
||||
body = fields.Html('Contents', default='', sanitize_style=True)
|
||||
subject = fields.Char('Subject', compute='_compute_template_values', readonly=False, store=True)
|
||||
body = fields.Html('Contents', sanitize_style=True, compute='_compute_template_values', readonly=False, store=True)
|
||||
attachment_ids = fields.Many2many(
|
||||
'ir.attachment', 'survey_mail_compose_message_ir_attachments_rel', 'wizard_id', 'attachment_id',
|
||||
string='Attachments')
|
||||
@@ -137,12 +137,16 @@ class SurveyInvite(models.TransientModel):
|
||||
_('The following recipients have no user account: %s. You should create user accounts for them or allow external signup in configuration.' %
|
||||
(','.join(invalid_partners.mapped('name')))))
|
||||
|
||||
@api.onchange('template_id')
|
||||
def _onchange_template_id(self):
|
||||
""" UPDATE ME """
|
||||
if self.template_id:
|
||||
self.subject = self.template_id.subject
|
||||
self.body = self.template_id.body_html
|
||||
@api.depends('template_id')
|
||||
def _compute_template_values(self):
|
||||
for invite in self:
|
||||
if not invite.subject:
|
||||
invite.subject = ''
|
||||
if not invite.body:
|
||||
invite.body = ''
|
||||
if invite.template_id:
|
||||
invite.subject = invite.template_id.subject
|
||||
invite.body = invite.template_id.body_html
|
||||
|
||||
@api.model
|
||||
def create(self, values):
|
||||
|
||||
Reference in New Issue
Block a user