first push message
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
from odoo import models, fields, api
|
||||
import json
|
||||
import textwrap
|
||||
|
||||
class SurveySurvey(models.Model):
|
||||
_inherit = 'survey.survey'
|
||||
|
||||
def get_dashboard_data(self):
|
||||
self.ensure_one()
|
||||
# Get completed responses only
|
||||
completed = self.user_input_ids.filtered(lambda u: u.state == 'done')
|
||||
total = len(completed)
|
||||
completion_rate = round((total / max(len(self.user_input_ids), 1)) * 100, 1) if self.user_input_ids else 0
|
||||
|
||||
questions_data = []
|
||||
for q in self.question_and_page_ids:
|
||||
if q.is_page:
|
||||
questions_data.append({'type': 'page', 'id': q.id, 'title': q.title or ''})
|
||||
continue
|
||||
|
||||
# Filter lines for this question
|
||||
lines = completed.mapped('user_input_line_ids').filtered(lambda l: l.question_id == q)
|
||||
|
||||
q_data = {
|
||||
'type': 'question',
|
||||
'id': q.id,
|
||||
'title': q.title or '',
|
||||
'qtype': q.question_type or '',
|
||||
'stats': [],
|
||||
'text_answers': []
|
||||
}
|
||||
|
||||
# Choice / Matrix / Scale
|
||||
if q.question_type in ['simple_choice', 'multiple_choice', 'matrix', 'scale']:
|
||||
for ans in q.suggested_answer_ids:
|
||||
count = len(lines.filtered(lambda l: l.suggested_answer_id == ans))
|
||||
pct = round((count / total * 100) if total else 0, 2)
|
||||
q_data['stats'].append({
|
||||
'label': ans.value or '',
|
||||
'count': count,
|
||||
'percent': pct
|
||||
})
|
||||
|
||||
# Text / Char
|
||||
elif q.question_type in ['text_box', 'char_box']:
|
||||
for line in lines:
|
||||
val = line.value_text_box or line.value_char_box
|
||||
if val:
|
||||
q_data['text_answers'].append(str(val))
|
||||
|
||||
# Numerical / Date
|
||||
elif q.question_type in ['numerical_box', 'date', 'datetime']:
|
||||
for line in lines:
|
||||
val = getattr(line, f'value_{q.question_type}', None)
|
||||
if val is not None:
|
||||
q_data['text_answers'].append(str(val))
|
||||
|
||||
questions_data.append(q_data)
|
||||
|
||||
# ✅ Serialize in Python (fixes QWeb KeyError: 'JSON')
|
||||
questions_json = json.dumps(questions_data, default=str, ensure_ascii=False)
|
||||
|
||||
return {
|
||||
'survey': self,
|
||||
'total_responses': total,
|
||||
'completion_rate': completion_rate,
|
||||
'questions': questions_data,
|
||||
'questions_json': questions_json,
|
||||
'print_url': f'/survey/print/{self.access_token}' if self.access_token else '#'
|
||||
}
|
||||
|
||||
|
||||
class SurveyUserInputLine(models.Model):
|
||||
_inherit = 'survey.user_input.line'
|
||||
|
||||
display_answer = fields.Char(
|
||||
string="Normalized Answer",
|
||||
compute='_compute_display_answer',
|
||||
store=True,
|
||||
index=True
|
||||
)
|
||||
|
||||
@api.depends('answer_type',
|
||||
'value_char_box', 'value_text_box', 'value_numerical_box',
|
||||
'value_scale', 'value_date', 'value_datetime',
|
||||
'suggested_answer_id', 'suggested_answer_id.value',
|
||||
'matrix_row_id', 'matrix_row_id.value')
|
||||
def _compute_display_answer(self):
|
||||
for line in self:
|
||||
answer = ''
|
||||
|
||||
# 🟢 Choice Questions (simple_choice, multiple_choice, matrix)
|
||||
if line.answer_type == 'suggestion':
|
||||
col_val = line.suggested_answer_id.value if line.suggested_answer_id else ''
|
||||
row_val = line.matrix_row_id.value if line.matrix_row_id else ''
|
||||
|
||||
if row_val and col_val:
|
||||
# Matrix question: "Row Label: Column Label"
|
||||
answer = f"{row_val}: {col_val}"
|
||||
else:
|
||||
# Simple/Multiple choice: just the selected option
|
||||
answer = col_val
|
||||
|
||||
# 📝 Text Answers
|
||||
elif line.answer_type == 'char_box':
|
||||
answer = (line.value_char_box or '').strip()
|
||||
elif line.answer_type == 'text_box':
|
||||
# Optional: truncate long text for dashboard readability
|
||||
txt = (line.value_text_box or '').strip()
|
||||
answer = textwrap.shorten(txt, width=100, placeholder=" [...]") if txt else ''
|
||||
|
||||
# 🔢 Numeric Answers
|
||||
elif line.answer_type == 'numerical_box':
|
||||
answer = str(line.value_numerical_box) if line.value_numerical_box is not None else ''
|
||||
elif line.answer_type == 'scale':
|
||||
answer = str(line.value_scale) if line.value_scale else ''
|
||||
|
||||
# 📅 Date/Time Answers
|
||||
elif line.answer_type == 'date':
|
||||
answer = fields.Date.to_string(line.value_date) if line.value_date else ''
|
||||
elif line.answer_type == 'datetime':
|
||||
answer = fields.Datetime.to_string(
|
||||
fields.Datetime.context_timestamp(self.env.user, line.value_datetime)
|
||||
) if line.value_datetime else ''
|
||||
|
||||
# ⚪ Skipped or Unknown
|
||||
else:
|
||||
answer = 'Skipped' if line.skipped else ''
|
||||
|
||||
line.display_answer = answer
|
||||
Reference in New Issue
Block a user