Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[IMP] Conditional survey questions' usability #23

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 5 additions & 22 deletions survey_conditional_questions/__manifest__.py
Original file line number Diff line number Diff line change
@@ -1,36 +1,19 @@
##############################################################################
#
# Copyright (C) 2015 ADHOC SA (http://www.adhoc.com.ar)
# All Rights Reserved.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################
# © 2015 ADHOC SA (http://www.adhoc.com.ar)
# © 2020 Opener B.V. (https://opener.amsterdam)
# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl.html).
{
'name': 'Survey Conditional Questions',
'version': '11.0.1.1.0',
'version': '11.0.1.2.0',
'category': 'Warehouse Management',
'sequence': 14,
'summary': '',
'author': 'ADHOC SA',
'author': 'ADHOC SA, Opener B.V.',
'website': 'www.adhoc.com.ar',
'license': 'AGPL-3',
'images': [
],
'depends': [
'survey',
'website'
],
'data': [
'views/survey_question_views.xml',
Expand Down
84 changes: 26 additions & 58 deletions survey_conditional_questions/controllers/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
# directory
##############################################################################

import json
import logging
from odoo.addons.survey.controllers.main import WebsiteSurvey
from odoo import http
Expand All @@ -14,62 +15,29 @@

class SurveyConditional(WebsiteSurvey):

# TODO deberiamos heredar esto correctamente
@http.route()
def fill_survey(self, survey, token, prev=None, **post):
'''Display and validates a survey'''
Survey = request.env['survey.survey']
UserInput = request.env['survey.user_input']

# Controls if the survey can be displayed
errpage = self._check_bad_cases(survey)
if errpage:
return errpage

# Load the user_input
user_input = UserInput.sudo().search([('token', '=', token)], limit=1)
if not user_input: # Invalid token
return request.render("website.403")

# Do not display expired survey (even if some pages have already been
# displayed -- There's a time for everything!)
errpage = self._check_deadline(user_input)
if errpage:
return errpage

# Select the right page
if user_input.state == 'new': # First page
page, page_nr, last = Survey.next_page(
user_input, 0, go_back=False)
data = {'survey': survey, 'page': page,
'page_nr': page_nr, 'token': user_input.token}
data['hide_question_ids'] = UserInput.get_list_questions(
survey, user_input)
if last:
data.update({'last': True})
return request.render('survey.survey', data)
elif user_input.state == 'done': # Display success message
return request.render(
'survey.sfinished',
{'survey': survey, 'token': token, 'user_input': user_input})
elif user_input.state == 'skip':
flag = (True if prev and prev == 'prev' else False)
page, page_nr, last = Survey.next_page(
user_input, user_input.last_displayed_page_id.id, go_back=flag)

# special case if you click "previous" from the last page,
# then leave the survey, then reopen it from the URL, avoid crash
if not page:
page, page_nr, last = Survey.next_page(
user_input, user_input.last_displayed_page_id.id,
go_back=True)

data = {'survey': survey, 'page': page,
'page_nr': page_nr, 'token': user_input.token}
if last:
data.update({'last': True})
data['hide_question_ids'] = UserInput.get_list_questions(
survey, user_input)
return request.render('survey.survey', data)
@http.route(
['/survey/hidden/<model("survey.survey"):survey>/<string:token>'
'/<int:stored>'],
type='http', auth='public', website=True)
def hidden(self, survey, token, stored, **post):
""" Pass the lists of hidden questions and pages to be applied in the
Javascript.
:param stored: indicate if we can rely on stored answers from a
completed survey, or if we have to determine the hidden questions from
the answers filled in so far. """
ret = {'hidden_pages': [], 'hidden_questions': []}
user_input = request.env['survey.user_input'].sudo().search(
[('token', '=', token)])
if stored:
questions = user_input.user_input_line_ids.filtered(
'hidden').mapped('question_id')
else:
return request.render("website.403")
questions = user_input.get_hidden_questions()
for question in questions:
question_tag = '%s_%s_%s' % (
question.survey_id.id, question.page_id.id, question.id)
ret['hidden_questions'].append(question_tag)
for page in questions.mapped('page_id'):
if not page.question_ids - questions:
ret['hidden_pages'].append(page.id)
return json.dumps(ret)
4 changes: 2 additions & 2 deletions survey_conditional_questions/i18n/en.po
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ msgid "Conditional Question"
msgstr "Conditional Question"

#. module: survey_conditional_questions
#: help:survey.question,question_conditional_id:0
#: help:survey.question,triggering_question_id:0
msgid "In order to edit this field you should first save the question"
msgstr "In order to edit this field you should first save the question"

#. module: survey_conditional_questions
#: field:survey.question,question_conditional_id:0
#: field:survey.question,triggering_question_id:0
msgid "Question"
msgstr "Question"

Expand Down
4 changes: 2 additions & 2 deletions survey_conditional_questions/i18n/es.po
Original file line number Diff line number Diff line change
Expand Up @@ -29,12 +29,12 @@ msgid "Conditional Question"
msgstr "Pregunta Condicional"

#. module: survey_conditional_questions
#: model:ir.model.fields,help:survey_conditional_questions.field_survey_question_question_conditional_id
#: model:ir.model.fields,help:survey_conditional_questions.field_survey_question_triggering_question_id
msgid "In order to edit this field you should first save the question"
msgstr "Para editar este campo , primero debe guardar la pregunta"

#. module: survey_conditional_questions
#: model:ir.model.fields,field_description:survey_conditional_questions.field_survey_question_question_conditional_id
#: model:ir.model.fields,field_description:survey_conditional_questions.field_survey_question_triggering_question_id
msgid "Question"
msgstr "Pregunta"

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ msgid "Conditional Question"
msgstr ""

#. module: survey_conditional_questions
#: help:survey.question,question_conditional_id:0
#: help:survey.question,triggering_question_id:0
msgid "In order to edit this field you should first save the question"
msgstr ""

#. module: survey_conditional_questions
#: field:survey.question,question_conditional_id:0
#: field:survey.question,triggering_question_id:0
msgid "Question"
msgstr ""

Expand Down
37 changes: 37 additions & 0 deletions survey_conditional_questions/migrations/11.0.1.2.0/pre-migrate.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import logging


def migrate(cr, version):
logger = logging.getLogger(
'survey_conditional_questions.migrations.11.0.1.3.0')

def rename(old, new):
""" Rename column if the old column exists and the new one does not """
cr.execute(
""" SELECT EXISTS(
SELECT *
FROM information_schema.columns
WHERE table_name='survey_question'
AND column_name=%s) """, (new,))
if cr.fetchone()[0]:
logger.info('Column %s already exists', new)
return
cr.execute(
""" SELECT EXISTS(
SELECT *
FROM information_schema.columns
WHERE table_name='survey_question'
AND column_name=%s) """, (old,))
if not cr.fetchone()[0]:
logger.info('Column %s does not exist', old)
return
logger.info('Renaming column %s to %s', new, old)
cr.execute(
""" ALTER TABLE survey_question
RENAME COLUMN %s to %s """ % (old, new))

for old, new in [
('conditional', 'is_conditional'),
('question_conditional_id', 'triggering_question_id'),
('answer_id', 'triggering_answer_id')]:
rename(old, new)
2 changes: 2 additions & 0 deletions survey_conditional_questions/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,7 @@
# For copyright and license notices, see __manifest__.py file in module root
# directory
##############################################################################
from . import survey_survey
from . import survey_question
from . import survey_user_input
from . import survey_user_input_line
33 changes: 9 additions & 24 deletions survey_conditional_questions/models/survey_question.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,56 +3,41 @@
# directory
##############################################################################
from odoo import api, fields, models
import logging

_logger = logging.getLogger(__name__)


class SurveyQuestion(models.Model):
_inherit = 'survey.question'

conditional = fields.Boolean(
is_conditional = fields.Boolean(
'Conditional Question',
copy=False,
# we add copy = false to avoid wrong link on survey copy,
# should be improoved
)
question_conditional_id = fields.Many2one(
triggering_question_id = fields.Many2one(
'survey.question',
'Question',
copy=False,
domain="[('survey_id', '=', survey_id)]",
help="In order to edit this field you should"
" first save the question"
)
answer_id = fields.Many2one(
triggering_answer_id = fields.Many2one(
'survey.label',
'Answer',
copy=False,
)

@api.multi
def validate_question(self, post, answer_tag):
''' Validate question, depending on question
type and parameters '''
""" Skip validation of hidden questions """
self.ensure_one()
try:
checker = getattr(self, 'validate_' + self.type)
except AttributeError:
_logger.warning(
checker.type +
": This type of question has no validation method")
return {}
else:
# TODO deberiamos emprolijar esto
if not self.question_conditional_id:
return checker(post, answer_tag)
if self.triggering_question_id:
input_answer_ids = self.env['survey.user_input_line'].search(
[('user_input_id.token', '=', post.get('token')),
('question_id', '=', self.question_conditional_id.id)])
('question_id', '=', self.triggering_question_id.id)])
for answers in input_answer_ids:
value_suggested = answers.value_suggested
if self.conditional and self.answer_id != value_suggested:
if (self.is_conditional and
self.triggering_answer_id != value_suggested):
return {}
else:
return checker(post, answer_tag)
return super(SurveyQuestion, self).validate_question(post, answer_tag)
28 changes: 28 additions & 0 deletions survey_conditional_questions/models/survey_survey.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
##############################################################################
# For copyright and license notices, see __manifest__.py file in module root
# directory
##############################################################################
from odoo import api, models


class SurveySurvey(models.Model):
_inherit = 'survey.survey'

@api.model
def next_page(self, user_input, page_id, go_back=False):
""" Skip pages that only have hidden questions on them,
except if its the last page or the first page (in which case there
is a configuration error in the survey). """
questions_to_hide = user_input.get_hidden_questions()
res = super(SurveySurvey, self).next_page(
user_input, page_id, go_back=go_back)
page, index, last = res
if page and not (page.question_ids - questions_to_hide):
if (not go_back and not last) or (go_back and index):
# Mark every question on this hidden page as hidden.
for question in page.question_ids:
self.env['survey.user_input_line'].update_hidden(
user_input, question)
return self.next_page(
user_input, page.id, go_back=go_back)
return res
24 changes: 12 additions & 12 deletions survey_conditional_questions/models/survey_user_input.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,17 +9,17 @@ class SurveyUserInput(models.Model):
_inherit = 'survey.user_input'

@api.model
def get_list_questions(self, survey, user_input):
obj_questions = self.env['survey.question']
questions_to_hide = []
question_ids = obj_questions.search(
[('survey_id', '=', survey.id)])
for question in question_ids.filtered('conditional'):
for question2 in question_ids.filtered(
lambda x: x == question.question_conditional_id):
input_answer_ids = user_input.user_input_line_ids.filtered(
def get_hidden_questions(self):
""" Return the questions that should be hidden based on the current
user input """
questions_to_hide = self.env['survey.question']
questions = self.survey_id.mapped('page_ids.question_ids')
for question in questions.filtered('is_conditional'):
for question2 in questions.filtered(
lambda x: x == question.triggering_question_id):
input_answer_ids = self.user_input_line_ids.filtered(
lambda x: x.question_id == question2)
for answers in input_answer_ids.filtered(
lambda x: x.value_suggested != question.answer_id):
questions_to_hide.append(question.id)
if question.triggering_answer_id not in (
input_answer_ids.mapped('value_suggested')):
questions_to_hide += question
return questions_to_hide
Loading