[REF] survey: replace dynamic survey.stage by a static state on survey.survey

Stages modification through the clickable statusbar wasn't very intuitive.
By fixing default behavior through states (and corresponding buttons), default user experience is simplified.

3 static states available : draft, open, closed

Form view: navigation through states with buttons
Kanban view: disabled modification of survey state

Task ID : 1949110

closes odoo/odoo#32325

Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
This commit is contained in:
Victor Feyens
2019-04-25 14:17:45 +00:00
parent 28e1686bc5
commit 50caae5bc0
20 changed files with 53 additions and 127 deletions
@@ -2,7 +2,7 @@
<odoo><data noupdate="1">
<record id="survey_recruitment_form" model="survey.survey">
<field name="title">Recruitment Form</field>
<field name="stage_id" ref="survey.stage_in_progress"/>
<field name="state">open</field>
<field name="access_mode">token</field>
<field name="category">hr_recruitment</field>
<field name="users_can_go_back" eval="True"/>
-2
View File
@@ -25,13 +25,11 @@ sent mails with personal token for the invitation of the survey.
'views/survey_report_templates.xml',
'views/survey_reports.xml',
'data/mail_template_data.xml',
'data/survey_data.xml',
'data/ir_actions_data.xml',
'security/survey_security.xml',
'security/ir.model.access.csv',
'views/assets.xml',
'views/survey_menus.xml',
'views/survey_stage_views.xml',
'views/survey_survey_views.xml',
'views/survey_user_views.xml',
'views/survey_question_views.xml',
+1 -1
View File
@@ -69,7 +69,7 @@ class Survey(http.Controller):
if survey_sudo.users_login_required and request.env.user._is_public():
return 'survey_auth'
if (survey_sudo.is_closed or not survey_sudo.active) and (not answer_sudo or not answer_sudo.test_entry):
if (survey_sudo.state == 'closed' or survey_sudo.state == 'draft' or not survey_sudo.active) and (not answer_sudo or not answer_sudo.test_entry):
return 'survey_closed'
if (not survey_sudo.page_ids and survey_sudo.questions_layout == 'page_per_section') or not survey_sudo.question_ids:
-24
View File
@@ -1,24 +0,0 @@
<?xml version="1.0"?>
<odoo>
<data noupdate="1">
<!-- Standard stages for surveys -->
<record id="stage_draft" model="survey.stage">
<field name="name">Draft</field>
<field name="sequence" eval="1" />
<field name="closed" eval="True" />
<field name="fold" eval="False" />
</record>
<record id="stage_in_progress" model="survey.stage">
<field name="name">In progress</field>
<field name="sequence" eval="2" />
<field name="closed" eval="False" />
<field name="fold" eval="False" />
</record>
<record id="stage_closed" model="survey.stage">
<field name="name">Closed</field>
<field name="sequence" eval="3" />
<field name="closed" eval="True" />
<field name="fold" eval="True" />
</record>
</data>
</odoo>
@@ -5,7 +5,7 @@
<record model="survey.survey" id="vendor_certification">
<field name="title">MyCompany Vendor Certification</field>
<field name="access_token">4ead4bc8-b8f2-4760-a682-1fde8ddb95ac</field>
<field name="stage_id" ref="survey.stage_in_progress" />
<field name="state">open</field>
<field name="access_mode">public</field>
<field name="users_can_go_back" eval="True" />
<field name="users_login_required" eval="True" />
+2 -2
View File
@@ -4,7 +4,7 @@
<record model="survey.survey" id="survey_feedback">
<field name="title">User Feedback Form</field>
<field name="access_token">b137640d-14d4-4748-9ef6-344ca256531e</field>
<field name="stage_id" ref="survey.stage_in_progress" />
<field name="state">open</field>
<field name="access_mode">public</field>
<field name="users_can_go_back" eval="True" />
<field name="questions_layout">page_per_section</field>
@@ -233,4 +233,4 @@
<field name="state">skip</field>
</record>
</data></odoo>
</data></odoo>
-1
View File
@@ -4,5 +4,4 @@
from . import ir_autovacuum
from . import survey_survey
from . import survey_question
from . import survey_stage
from . import survey_user
-19
View File
@@ -1,19 +0,0 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo import fields, models
class SurveyStage(models.Model):
_name = 'survey.stage'
_description = 'Survey Stage'
_order = 'sequence,id'
name = fields.Char(required=True, translate=True)
sequence = fields.Integer(default=1)
closed = fields.Boolean(help="If closed, people won't be able to answer to surveys in this column.")
fold = fields.Boolean(string="Folded in kanban view")
_sql_constraints = [
('positive_sequence', 'CHECK(sequence >= 0)', 'Sequence number MUST be a natural')
]
+26 -15
View File
@@ -21,9 +21,6 @@ class Survey(models.Model):
_rec_name = 'title'
_inherit = ['mail.thread', 'mail.activity.mixin']
def _get_default_stage_id(self):
return self.env['survey.stage'].search([], limit=1).id
def _get_default_access_token(self):
return str(uuid.uuid4())
@@ -37,9 +34,15 @@ class Survey(models.Model):
question_and_page_ids = fields.One2many('survey.question', 'survey_id', string='Sections and Questions', copy=True)
page_ids = fields.One2many('survey.question', string='Pages', compute="_compute_page_and_question_ids")
question_ids = fields.One2many('survey.question', string='Questions', compute="_compute_page_and_question_ids")
stage_id = fields.Many2one('survey.stage', string="Stage", default=lambda self: self._get_default_stage_id(),
ondelete="restrict", copy=False, group_expand='_read_group_stage_ids')
is_closed = fields.Boolean("Is closed", related='stage_id.closed', readonly=True)
state = fields.Selection(
string="Survey Stage",
selection=[
('draft', 'Draft'),
('open', 'In Progress'),
('closed', 'Closed'),
], default='draft', required=True,
group_expand='_read_group_states'
)
questions_layout = fields.Selection([
('one_page', 'One page with all the questions'),
('page_per_section', 'One page per section'),
@@ -174,13 +177,9 @@ class Survey(models.Model):
if self.is_time_limited and (not self.time_limit or self.time_limit <= 0):
self.time_limit = 10
@api.model
def _read_group_stage_ids(self, stages, domain, order):
""" Read group customization in order to display all the stages in the
kanban view, even if they are empty
"""
stage_ids = stages._search([], order=order, access_rights_uid=SUPERUSER_ID)
return stages.browse(stage_ids)
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]
# Public methods #
def copy_data(self, default=None):
@@ -245,7 +244,7 @@ class Survey(models.Model):
else:
if not self.active:
raise UserError(_('Creating token for archived surveys is not allowed.'))
elif self.is_closed:
elif self.state == 'closed':
raise UserError(_('Creating token for closed surveys is not allowed.'))
if self.access_mode == 'authentication':
# signup possible -> should have at least a partner to create an account
@@ -437,6 +436,18 @@ class Survey(models.Model):
# Actions
@api.multi
def action_draft(self):
self.write({'state': 'draft'})
@api.multi
def action_open(self):
self.write({'state': 'open'})
@api.multi
def action_close(self):
self.write({'state': 'closed'})
@api.multi
def action_start_survey(self):
""" Open the website page with the survey form """
@@ -457,7 +468,7 @@ class Survey(models.Model):
if (not self.page_ids and self.questions_layout == 'page_per_section') or not self.question_ids:
raise UserError(_('You cannot send an invitation for a survey that has no questions.'))
if self.stage_id.closed:
if self.state == 'closed':
raise UserError(_("You cannot send invitations for closed surveys."))
template = self.env.ref('survey.mail_template_user_input_invite', raise_if_not_found=False)
@@ -3,10 +3,6 @@ access_survey_all,survey.survey.all,model_survey_survey,,0,0,0,0
access_survey_user,survey.survey.user,model_survey_survey,base.group_user,0,0,0,0
access_survey_survey_user,survey.survey.survey.user,model_survey_survey,group_survey_user,1,1,1,1
access_survey_survey_manager,survey.survey.survey.manager,model_survey_survey,group_survey_manager,1,1,1,1
access_survey_stage_all,survey.stage.all,model_survey_stage,,0,0,0,0
access_survey_stage_user,survey.stage.user,model_survey_stage,base.group_user,0,0,0,0
access_survey_stage_survey_user,survey.stage.survey.user,model_survey_stage,group_survey_user,1,0,0,0
access_survey_stage_survey_manager,survey.stage.survey.manager,model_survey_stage,group_survey_manager,1,1,1,1
access_survey_question_all,survey.question.all,model_survey_question,,0,0,0,0
access_survey_question_user,survey.question.user,model_survey_question,base.group_user,0,0,0,0
access_survey_question_survey_user,survey.question.survey.user,model_survey_question,group_survey_user,1,1,1,1
1 id name model_id:id group_id:id perm_read perm_write perm_create perm_unlink
3 access_survey_user survey.survey.user model_survey_survey base.group_user 0 0 0 0
4 access_survey_survey_user survey.survey.survey.user model_survey_survey group_survey_user 1 1 1 1
5 access_survey_survey_manager survey.survey.survey.manager model_survey_survey group_survey_manager 1 1 1 1
access_survey_stage_all survey.stage.all model_survey_stage 0 0 0 0
access_survey_stage_user survey.stage.user model_survey_stage base.group_user 0 0 0 0
access_survey_stage_survey_user survey.stage.survey.user model_survey_stage group_survey_user 1 0 0 0
access_survey_stage_survey_manager survey.stage.survey.manager model_survey_stage group_survey_manager 1 1 1 1
6 access_survey_question_all survey.question.all model_survey_question 0 0 0 0
7 access_survey_question_user survey.question.user model_survey_question base.group_user 0 0 0 0
8 access_survey_question_survey_user survey.question.survey.user model_survey_question group_survey_user 1 1 1 1
@@ -56,28 +56,6 @@
<field name="perm_create" eval="1"/>
</record>
<record id="survey_stage_rule_survey_manager" model="ir.rule">
<field name="name">Survey stage: manager: all</field>
<field name="model_id" ref="survey.model_survey_stage"/>
<field name="domain_force">[(1, '=', 1)]</field>
<field name="groups" eval="[(4, ref('group_survey_manager'))]"/>
<field name="perm_unlink" eval="1"/>
<field name="perm_write" eval="1"/>
<field name="perm_read" eval="1"/>
<field name="perm_create" eval="1"/>
</record>
<record id="survey_stage_rule_survey_user_read" model="ir.rule">
<field name="name">Survey stage: officer: read all</field>
<field name="model_id" ref="survey.model_survey_stage"/>
<field name="domain_force">[(1, '=', 1)]</field>
<field name="groups" eval="[(4, ref('group_survey_user'))]"/>
<field name="perm_unlink" eval="0"/>
<field name="perm_write" eval="0"/>
<field name="perm_read" eval="1"/>
<field name="perm_create" eval="0"/>
</record>
<record id="survey_question_rule_survey_manager" model="ir.rule">
<field name="name">Survey question: manager: all</field>
<field name="model_id" ref="survey.model_survey_question"/>
+1 -1
View File
@@ -68,7 +68,7 @@ class SurveyCase(common.SavepointCase):
'access_mode': 'public',
'users_login_required': True,
'users_can_go_back': False,
'stage_id': self.env['survey.stage'].search([('closed', '=', False)]).id,
'state': 'open',
})
self.page_0 = self.env['survey.question'].sudo(self.survey_manager).create({
'title': 'First page',
@@ -51,7 +51,7 @@ class TestCertificationFlow(common.SurveyCase, HttpCase):
'certification_mail_template_id': self.env.ref('survey.mail_template_certification').id,
'is_time_limited': True,
'time_limit': 10,
'stage_id': self.env['survey.stage'].search([('closed', '=', False)]).id
'state': 'open',
})
q01 = self._add_question(
@@ -9,7 +9,7 @@ class TestSurveyComputePagesQuestions(common.SurveyCase):
with self.sudo(self.survey_manager):
survey = self.env['survey.survey'].create({
'title': 'Test compute survey',
'stage_id': self.env['survey.stage'].search([('closed', '=', False)]).id
'state': 'open',
})
page_0 = self.env['survey.question'].create({
+1 -1
View File
@@ -34,7 +34,7 @@ class TestSurveyFlow(common.SurveyCase, HttpCase):
'access_mode': 'public',
'users_login_required': False,
'questions_layout': 'page_per_section',
'stage_id': self.env['survey.stage'].search([('closed', '=', False)]).id
'state': 'open'
})
# First page is about customer data
+1 -1
View File
@@ -34,7 +34,7 @@ class TestSurveyInvite(common.SurveyCase):
# closed
self.env['survey.survey'].sudo(self.survey_manager).create({
'title': 'S0',
'stage_id': self.env['survey.stage'].search([('sequence', '=', 3)]).id,
'state': 'closed',
'question_and_page_ids': [
(0, 0, {'is_page': True, 'title': 'P0', 'sequence': 1}),
(0, 0, {'title': 'Q0', 'sequence': 2, 'question_type': 'free_text'})
@@ -1,19 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo>
<data>
<record model="ir.ui.view" id="survey_stage_form">
<field name="name">Form view for survey stage</field>
<field name="model">survey.stage</field>
<field name="arch" type="xml">
<form string="Stage">
<group col='4' colspan='4'>
<field name="name" />
<field name="closed" />
<field name="sequence" />
<field name="fold" />
</group>
</form>
</field>
</record>
</data>
</odoo>
+15 -9
View File
@@ -7,13 +7,16 @@
<field name="arch" type="xml">
<form string="Survey" class="o_survey_form">
<field name="id" invisible="1"/>
<field name="is_closed" invisible="1"/>
<header>
<button name="action_send_survey" string="Share" type="object" class="oe_highlight" attrs="{'invisible': [('id', '=', False)]}"/>
<button name="action_result_survey" string="View results" type="object" attrs="{'invisible': [('id', '=', False)]}"/>
<button name="action_test_survey" string="Test" type="object" attrs="{'invisible': [('id', '=', False)]}"/>
<button name="action_open" string="Start Survey" type="object" class="oe_highlight" attrs="{'invisible': ['|', ('state', '!=', 'draft'), ('id', '=', False)]}"/>
<button name="action_send_survey" string="Share" type="object" class="oe_highlight" states="open"/>
<button name="action_result_survey" string="See results" type="object" class="oe_highlight"
attrs="{'invisible': ['|', ('state', '=', 'draft'), ('answer_done_count', '&lt;=', 0)]}"/>
<button name="action_draft" string="Set to draft" type="object" states="closed"/>
<button name="action_test_survey" string="Test" type="object" attrs="{'invisible': ['|', ('state', '=', 'closed'), ('id', '=', False)]}"/>
<button name="action_print_survey" string="Print" type="object" attrs="{'invisible': [('id', '=', False)]}"/>
<field name="stage_id" widget="statusbar" options="{'clickable': '1'}"/>
<button name="action_close" string="Close" type="object" states="open"/>
<field name="state" widget="statusbar"/>
</header>
<sheet>
<div class="oe_button_box" name="button_box">
@@ -115,11 +118,14 @@
<field name="arch" type="xml">
<tree string="Survey">
<field name="active" invisible="1"/>
<field name="title" />
<field name="stage_id" />
<field name="certificate" invisible="1"/>
<field name="title"/>
<field name="state"/>
<field name="invite_count"/>
<field name="answer_count"/>
<field name="answer_done_count"/>
<button name="certificate" icon="fa-trophy" title="Certificate" aria-label="Certificate" attrs="{'invisible': [('certificate', '=', False)]}"/>
<!-- Tweak as icons aren't directly supported in xml -->
</tree>
</field>
</record>
@@ -127,8 +133,8 @@
<field name="name">Kanban view for survey</field>
<field name="model">survey.survey</field>
<field name="arch" type="xml">
<kanban default_group_by="stage_id">
<field name="stage_id" />
<kanban default_group_by="state">
<field name="state" />
<field name="title" />
<field name="answer_done_count" />
<field name="certificate" />
@@ -5,7 +5,7 @@
<record model="survey.survey" id="furniture_certification">
<field name="title">Furniture Creation Certification</field>
<field name="access_token">5632a4d7-48cf-4d25-8c52-2174d58cf50b</field>
<field name="stage_id" ref="survey.stage_in_progress" />
<field name="state">open</field>
<field name="access_mode">public</field>
<field name="users_can_go_back" eval="True" />
<field name="users_login_required" eval="True" />
@@ -18,7 +18,7 @@ class TestCourseCertificationFailureFlow(SurveyCase):
'is_attempts_limited': True,
'passing_score': 100.0,
'attempts_limit': 2,
'stage_id': self.env['survey.stage'].search([('closed', '=', False)]).id
'state': 'open',
})
self._add_question(