@@ -148,8 +150,8 @@
Answers
survey.user_input
tree,kanban,form
-
-
+
+
{'search_default_group_by_survey': True}
[('test_entry', '=', False)]
From ee5649cdff08b0cd413a8d1d6b0d01aea290e50a Mon Sep 17 00:00:00 2001
From: Jitendra Prajapati
Date: Thu, 29 Aug 2019 13:11:32 +0000
Subject: [PATCH 3/4] [IMP] survey: improve user answers model and display in
backend
PURPOSE
Perform a back2basics review of survey to improve daily use, new user
onboarding and labelling.
SPECIFICATIONS
Order answer lines following question order.
Display section in answer lines form view to better understand question and
answer organization.
Add a correct flag on answer lines and display it in user input embedded
view in order to know which line are correct.
LINKS
Task 2039068
PR #36229
---
addons/survey/models/survey_user.py | 11 +++++++++++
addons/survey/views/survey_user_views.xml | 5 ++++-
2 files changed, 15 insertions(+), 1 deletion(-)
diff --git a/addons/survey/models/survey_user.py b/addons/survey/models/survey_user.py
index b7fa5f1f92a..8cfa9e9dde4 100644
--- a/addons/survey/models/survey_user.py
+++ b/addons/survey/models/survey_user.py
@@ -199,12 +199,14 @@ class SurveyUserInputLine(models.Model):
_name = 'survey.user_input_line'
_description = 'Survey User Input Line'
_rec_name = 'user_input_id'
+ _order = 'question_sequence,id'
# survey data
user_input_id = fields.Many2one('survey.user_input', string='User Input', ondelete='cascade', required=True)
survey_id = fields.Many2one(related='user_input_id.survey_id', string='Survey', store=True, readonly=False)
question_id = fields.Many2one('survey.question', string='Question', ondelete='cascade', required=True)
page_id = fields.Many2one(related='question_id.page_id', string="Section", readonly=False)
+ question_sequence = fields.Integer('Sequence', related='question_id.sequence', store=True)
# answer
skipped = fields.Boolean('Skipped')
answer_type = fields.Selection([
@@ -222,6 +224,15 @@ class SurveyUserInputLine(models.Model):
value_suggested = fields.Many2one('survey.label', string="Suggested answer")
value_suggested_row = fields.Many2one('survey.label', string="Row answer")
answer_score = fields.Float('Score')
+ answer_is_correct = fields.Boolean('Correct', compute='_compute_answer_is_correct')
+
+ @api.depends('value_suggested', 'question_id')
+ def _compute_answer_is_correct(self):
+ for answer in self:
+ if answer.value_suggested and answer.question_id.question_type in ['simple_choice', 'multiple_choice']:
+ answer.answer_is_correct = answer.value_suggested.is_correct
+ else:
+ answer.answer_is_correct = False
@api.constrains('skipped', 'answer_type')
def _answered_or_skipped(self):
diff --git a/addons/survey/views/survey_user_views.xml b/addons/survey/views/survey_user_views.xml
index fd7249da958..3d9384ead5d 100644
--- a/addons/survey/views/survey_user_views.xml
+++ b/addons/survey/views/survey_user_views.xml
@@ -66,11 +66,14 @@
+
+
-
+
+
From 240e860f24832d0201e968fa30c837792a6a8816 Mon Sep 17 00:00:00 2001
From: Jitendra Prajapati
Date: Thu, 29 Aug 2019 15:20:13 +0000
Subject: [PATCH 4/4] [IMP] survey: add an overall correctness graph when
finishing a certification
PURPOSE
Perform a back2basics review of survey to improve daily use, new user
onboarding and labelling.
SPECIFICATIONS
When finishing a certification survey, add an overall correctness circular
graph. Quarters are
* correct
* partially (if multiple corrects answers on the survey);
* incorrect
* unanswered
Questions without points are not displayed in this graph.
LINKS
Task 2039068
PR #36229
---
addons/survey/controllers/main.py | 8 +++++
addons/survey/models/survey_survey.py | 33 ++++++++++++++++++
addons/survey/static/src/js/survey_result.js | 35 ++++++++++++++++++++
addons/survey/views/survey_templates.xml | 9 +++++
4 files changed, 85 insertions(+)
diff --git a/addons/survey/controllers/main.py b/addons/survey/controllers/main.py
index 9ab1f366ac3..7eabe92f733 100644
--- a/addons/survey/controllers/main.py
+++ b/addons/survey/controllers/main.py
@@ -651,4 +651,12 @@ class Survey(http.Controller):
values = {'survey': survey, 'answer': answer}
if token:
values['token'] = token
+ if survey.scoring_type != 'no_scoring' and survey.certificate:
+ answer_perf = survey._get_answers_correctness(answer)[answer]
+ values['graph_data'] = json.dumps([
+ {"text": "Correct", "count": answer_perf['correct']},
+ {"text": "Partially", "count": answer_perf['partial']},
+ {"text": "Incorrect", "count": answer_perf['incorrect']},
+ {"text": "Unanswered", "count": answer_perf['skipped']}
+ ])
return values
diff --git a/addons/survey/models/survey_survey.py b/addons/survey/models/survey_survey.py
index d3ea6462a5a..5418d414603 100644
--- a/addons/survey/models/survey_survey.py
+++ b/addons/survey/models/survey_survey.py
@@ -622,6 +622,39 @@ class Survey(models.Model):
return result
+ def _get_answers_correctness(self, user_answers):
+ if not user_answers.mapped('survey_id') == self:
+ raise UserError(_('Invalid performance computation'))
+
+ res = dict((user_answer, {
+ 'correct': 0,
+ 'incorrect': 0,
+ 'partial': 0,
+ 'skipped': 0,
+ }) for user_answer in user_answers)
+
+ scored_questions = self.question_ids.filtered(
+ lambda question: question.question_type in ['simple_choice', 'multiple_choice']
+ )
+
+ for question in scored_questions:
+ question_answer_correct = question.labels_ids.filtered(lambda answer: answer.is_correct)
+ for user_answer in user_answers:
+ user_answer_lines_question = user_answer.user_input_line_ids.filtered(lambda line: line.question_id == question)
+ user_answer_correct = user_answer_lines_question.filtered(lambda line: line.answer_is_correct and not line.skipped).mapped('value_suggested')
+ user_answer_incorrect = user_answer_lines_question.filtered(lambda line: not line.answer_is_correct and not line.skipped)
+
+ if user_answer_correct == question_answer_correct:
+ res[user_answer]['correct'] += 1
+ elif user_answer_correct and user_answer_correct < question_answer_correct:
+ res[user_answer]['partial'] += 1
+ if not user_answer_correct and user_answer_incorrect:
+ res[user_answer]['incorrect'] += 1
+ if not user_answer_correct and not user_answer_incorrect:
+ res[user_answer]['skipped'] += 1
+
+ return res
+
# ------------------------------------------------------------
# GAMIFICATION / BADGES
# ------------------------------------------------------------
diff --git a/addons/survey/static/src/js/survey_result.js b/addons/survey/static/src/js/survey_result.js
index 6e63d473ea4..380a5c893a8 100644
--- a/addons/survey/static/src/js/survey_result.js
+++ b/addons/survey/static/src/js/survey_result.js
@@ -2,6 +2,7 @@ odoo.define('survey.result', function (require) {
'use strict';
require('web.dom_ready');
+var _t = require('web.core')._t;
if(!$('.js_surveyresult').length) {
return Promise.reject("DOM doesn't contain '.js_surveyresult'");
@@ -159,6 +160,35 @@ if(!$('.js_surveyresult').length) {
return chartConfig;
}
+ //initialize doughnut Chart
+ function init_doughnut_chart(graph_data, quizz_score){
+ var data = graph_data.map(function (point) {
+ return point.count;
+ });
+ var chartConfig = {
+ type: 'doughnut',
+ data: {
+ labels: graph_data.map(function (point) {
+ return point.text;
+ }),
+ datasets: [{
+ label: '',
+ data: data,
+ backgroundColor: data.map(function (val, index) {
+ return D3_COLORS[index % 20];
+ }),
+ }]
+ },
+ options: {
+ title: {
+ display: true,
+ text: _.str.sprintf(_t("Overall Performance %.2f%s"), parseFloat(quizz_score), '%'),
+ },
+ }
+ };
+ return chartConfig;
+ }
+
//load chart to svg element chart:initialized chart, response:AJAX response, quistion_id:if of survey question, tick_limit:text length limit
function load_chart(chartConfig, containerSelector){
var $container = $(containerSelector).css({position: 'relative'});
@@ -187,6 +217,11 @@ if(!$('.js_surveyresult').length) {
chartConfig = init_pie_chart(graph_data);
return load_chart(chartConfig, containerSelector);
}
+ else if (graph_type === 'doughnut') {
+ var quizz_score = $(graph).attr("quizz-score") || 0.0;
+ chartConfig = init_doughnut_chart(graph_data, quizz_score);
+ return load_chart(chartConfig, containerSelector);
+ }
});
var $scoringResultsChart = $('#scoring_results_chart');
diff --git a/addons/survey/views/survey_templates.xml b/addons/survey/views/survey_templates.xml
index 569da41c1c5..4906e4e6c0e 100644
--- a/addons/survey/views/survey_templates.xml
+++ b/addons/survey/views/survey_templates.xml
@@ -57,6 +57,15 @@
+
+