1 # -*- encoding: utf-8 -*-
2 ##############################################################################
4 # OpenERP, Open Source Management Solution
5 # Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
8 # This program is free software: you can redistribute it and/or modify
9 # it under the terms of the GNU Affero General Public License as published by
10 # the Free Software Foundation, either version 3 of the License, or
11 # (at your option) any later version.
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU Affero General Public License for more details.
18 # You should have received a copy of the GNU Affero General Public License
19 # along with this program. If not, see <http://www.gnu.org/licenses/>.
21 ##############################################################################
24 from report.interface import report_rml
25 from tools import to_xml
28 from report import report_sxw
30 class survey_analysis(report_rml):
31 def create(self, cr, uid, ids, datas, context):
32 surv_obj = pooler.get_pool(cr.dbname).get('survey')
33 user_obj = pooler.get_pool(cr.dbname).get('res.users')
34 rml_obj=report_sxw.rml_parse(cr, uid, surv_obj._name,context)
35 company=user_obj.browse(cr,uid,[uid],context)[0].company_id
37 rml ="""<document filename="Survey Analysis Report.pdf">
38 <template pageSize="(595.0,842.0)" title="Survey Analysis" author="OpenERP S.A.(sales@openerp.com)" allowSplitting="20">
40 <frame id="first" x1="1.3cm" y1="1.5cm" width="18.4cm" height="26.5cm"/>
43 <stroke color="black"/>
44 <setFont name="DejaVu Sans" size="8"/>
45 <drawString x="1.3cm" y="28.3cm"> """+to_xml(rml_obj.formatLang(time.strftime("%Y-%m-%d %H:%M:%S"),date_time=True))+"""</drawString>
46 <setFont name="DejaVu Sans Bold" size="10"/>
47 <drawString x="9.8cm" y="28.3cm">"""+ to_xml(company.name) +"""</drawString>
48 <stroke color="#000000"/>
49 <lines>1.3cm 28.1cm 20cm 28.1cm</lines>
54 <blockTableStyle id="Table1">
55 <blockAlignment value="LEFT"/>
56 <blockValign value="TOP"/>
57 <lineStyle kind="LINEBELOW" colorName="#e6e6e6"/>
59 <blockTableStyle id="Table2">
60 <blockAlignment value="LEFT"/>
61 <blockValign value="TOP"/>
63 <blockTableStyle id="Table3">
64 <blockAlignment value="LEFT"/>
65 <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="1,0" stop="2,-1"/>
66 <blockValign value="TOP"/>
68 <blockTableStyle id="Table4">
69 <blockAlignment value="LEFT"/>
70 <blockValign value="TOP"/>
71 <lineStyle kind="LINEBELOW" colorName="#000000" start="0,-1" stop="1,-1"/>
73 <blockTableStyle id="Table5">
74 <blockAlignment value="LEFT"/>
75 <blockValign value="TOP"/>
76 <lineStyle kind="LINEBELOW" colorName="#8f8f8f" start="0,-1" stop="1,-1"/>
78 <blockTableStyle id="Table_heading">
79 <blockAlignment value="LEFT"/>
80 <blockValign value="TOP"/>
81 <lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="0,0" stop="-1,-1"/>
82 <lineStyle kind="LINEAFTER" colorName="#e6e6e6" start="0,0" stop="-1,-1"/>
83 <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="0,0" stop="-1,-1"/>
84 <lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="0,0" stop="-1,-1"/>
86 <blockTableStyle id="Table_head_2">
87 <blockAlignment value="LEFT"/>
88 <blockValign value="TOP"/>
89 <lineStyle kind="LINEBEFORE" colorName="#e6e6e6" start="0,0" stop="-1,-1"/>
90 <lineStyle kind="LINEAFTER" colorName="#e6e6e6" start="0,0" stop="-1,-1"/>
91 <lineStyle kind="LINEBELOW" colorName="#e6e6e6" start="0,0" stop="-1,-1"/>
92 <lineStyle kind="LINEABOVE" colorName="#e6e6e6" start="0,0" stop="-1,-1"/>
95 <paraStyle name="all" alignment="justify"/>
97 <paraStyle name="answer_right" alignment="RIGHT" fontName="helvetica" fontSize="09.0" leftIndent="2.0"/>
98 <paraStyle name="Standard1" fontName="helvetica-bold" alignment="RIGHT" fontSize="09.0"/>
99 <paraStyle name="Standard" alignment="LEFT" fontName="Helvetica-Bold" fontSize="11.0"/>
100 <paraStyle name="header1" fontName="Helvetica" fontSize="11.0"/>
101 <paraStyle name="response" fontName="Helvetica-oblique" fontSize="9.5"/>
102 <paraStyle name="response-bold" fontName="Helvetica-bold" fontSize="9" alignment="RIGHT" />
103 <paraStyle name="page" fontName="helvetica" fontSize="11.0" leftIndent="0.0"/>
104 <paraStyle name="question" fontName="helvetica-boldoblique" fontSize="10.0" leftIndent="3.0"/>
105 <paraStyle name="answer_bold" fontName="Helvetica-Bold" fontSize="09.0" leftIndent="2.0"/>
106 <paraStyle name="answer" fontName="helvetica" fontSize="09.0" leftIndent="2.0"/>
107 <paraStyle name="Title" fontName="helvetica" fontSize="20.0" leading="15" spaceBefore="6.0" spaceAfter="6.0" alignment="CENTER"/>
108 <paraStyle name="terp_tblheader_General_Centre" fontName="Helvetica-Bold" fontSize="9.0" leading="10" alignment="CENTER" spaceBefore="6.0" spaceAfter="6.0"/>
109 <paraStyle name="terp_default_Centre_8" fontName="Helvetica" fontSize="9.0" leading="10" alignment="CENTER" spaceBefore="0.0" spaceAfter="0.0"/>
110 <paraStyle name="terp_default_Center_heading" fontName="Helvetica-bold" fontSize="9.0" leading="10" alignment="CENTER" spaceBefore="0.0" spaceAfter="0.0"/>
111 <paraStyle name="P2" fontName="Helvetica" fontSize="14.0" leading="15" spaceBefore="6.0" spaceAfter="6.0"/>
116 if datas.has_key('form') and datas['form']['survey_ids']:
117 ids = datas['form']['survey_ids']
119 for survey in surv_obj.browse(cr, uid, ids):
121 <para style="Title">Answers Summary</para>
122 <para style="Standard"><font></font></para>
124 <font color="white"> </font>
126 <blockTable colWidths="280.0,100.0,120.0" style="Table_heading">
129 <para style="terp_tblheader_General_Centre">Survey Title </para>
132 <para style="terp_tblheader_General_Centre">Total Started Survey </para>
135 <para style="terp_tblheader_General_Centre">Total Completed Survey </para>
139 <blockTable colWidths="280.0,100.0,120.0" style="Table_head_2">
142 <para style="terp_default_Centre_8">""" + to_xml(tools.ustr(survey.title)) + """</para>
145 <para style="terp_default_Centre_8">""" + str(survey.tot_start_survey) + """</para>
148 <para style="terp_default_Centre_8">""" + str(survey.tot_comp_survey) + """</para>
153 <font color="white"> </font>
155 for page in survey.page_ids:
156 rml += """ <blockTable colWidths="500" style="Table4">
158 <td><para style="page">Page :- """ + to_xml(tools.ustr(page.title)) + """</para></td>
161 for que in page.question_ids:
162 rml +="""<blockTable colWidths="500" style="Table5">
164 <td><para style="question">""" + to_xml(tools.ustr(que.question)) + """</para></td>
169 if que.type in ['matrix_of_choices_only_one_ans','matrix_of_choices_only_multi_ans']:
170 cols_widhts.append(200)
171 for col in range(0, len(que.column_heading_ids) + 1):
172 cols_widhts.append(float(300 / (len(que.column_heading_ids) + 1)))
173 colWidths = ",".join(map(tools.ustr, cols_widhts))
174 matrix_ans = [(0,'')]
176 for col in que.column_heading_ids:
177 if col.title not in matrix_ans:
178 matrix_ans.append((col.id,col.title))
179 rml += """<blockTable colWidths=" """ + colWidths + """ " style="Table1"><tr>"""
180 for mat_col in range(0, len(matrix_ans)):
181 rml+="""<td><para style="response">""" + to_xml(tools.ustr(matrix_ans[mat_col][1])) + """</para></td>"""
182 rml += """<td><para style="response-bold">Answer Count</para></td>
184 last_col = cols_widhts[-1]
186 for ans in que.answer_choice_ids:
187 rml += """<tr><td><para style="answer">""" + to_xml(tools.ustr(ans.answer)) + """</para></td>"""
188 cr.execute("select count(id) from survey_response_answer sra where sra.answer_id = %s", (ans.id,))
189 tot_res = cr.fetchone()[0]
190 cr.execute("select count(id) ,sra.column_id from survey_response_answer sra where sra.answer_id=%s group by sra.column_id", (ans.id,))
191 calc_res = cr.dictfetchall()
192 for mat_col in range(1, len(matrix_ans)):
196 if cal['column_id'] == matrix_ans[mat_col][0]:
197 cal_count = cal['count']
199 percantage = round(float(cal_count)*100 / tot_res,2)
201 rml += """<td color="#FFF435"><para style="answer_bold">""" + tools.ustr(percantage) +"% (" + tools.ustr(cal_count) + """)</para></td>"""
203 rml += """<td color="#FFF435"><para style="answer">""" + tools.ustr(percantage) +"% (" + tools.ustr(cal_count) + """)</para></td>"""
204 rml += """<td><para style="answer_right">""" + tools.ustr(tot_res) + """</para></td>
206 rml += """</blockTable>"""
208 if que.is_comment_require:
209 cr.execute("select count(id) from survey_response_line where question_id = %s and comment != ''",(que.id,))
210 tot_res = cr.fetchone()[0]
211 rml += """<blockTable colWidths=" """+ str(500 - last_col) +"," + str(last_col) + """ " style="Table1"><tr><td><para style="answer_right">""" + to_xml(tools.ustr(que.comment_label)) + """</para></td>
212 <td><para style="answer">""" + tools.ustr(tot_res) + """</para></td></tr></blockTable>"""
214 elif que.type in['multiple_choice_only_one_ans', 'multiple_choice_multiple_ans', 'multiple_textboxes','date_and_time','date','multiple_textboxes_diff_type']:
215 rml += """<blockTable colWidths="240.0,210,50.0" style="Table1">"""
217 <td> <para style="Standard"> </para></td>
218 <td> <para style="terp_default_Center_heading">Answer Percentage</para></td>
219 <td> <para style="response-bold">Answer Count</para></td>
222 for ans in que.answer_choice_ids:
223 progress = ans.average * 7 / 100
224 rml += """<tr><td><para style="answer">""" + to_xml(tools.ustr(ans.answer)) + """</para></td>
227 <stroke color="lightslategray"/>
228 <rect x="0.1cm" y="-0.45cm" width="7.2 cm" height="0.5cm" fill="no" stroke="yes" round="0.1cm"/>
231 rml += """<fill color="lightsteelblue"/>
232 <rect x="0.2cm" y="-0.35cm" width='""" + tools.ustr(str(float(progress)) +'cm') + """' height="0.3cm" fill="yes" stroke="no" round="0.1cm"/>"""
234 <fill color="black"/>
235 <setFont name="Helvetica" size="9"/>
236 <drawString x="3.2cm" y="-0.30cm">""" + tools.ustr(ans.average) + """%</drawString></illustration>
238 <td><para style="answer_right">""" + tools.ustr(ans.response) + """</para></td></tr>"""
239 rml += """</blockTable>"""
241 if que.is_comment_require:
242 # if que.make_comment_field:
243 # cr.execute("select count(id) from survey_response_line where question_id = %s and comment != ''", (que.id,))
244 # tot_res = cr.fetchone()[0]
247 # tot_avg = round(float(tot_res * 100)/ que.tot_resp,2)
248 # rml+="""<blockTable colWidths="280.0,120,100.0" style="Table1"><tr><td><para style="answer">""" +to_xml(tools.ustr(que.comment_label)) + """</para></td>
249 # <td><para style="answer">""" + str(tot_avg) + """%</para></td>
250 # <td><para style="answer">""" + tools.ustr(tot_res) + """</para></td></tr></blockTable>"""
252 cr.execute("select count(id) from survey_response_line where question_id = %s and comment != ''", (que.id,))
253 tot_res = cr.fetchone()[0]
254 rml += """<blockTable colWidths="450.0,50.0" style="Table1"><tr><td><para style="answer_right">""" + to_xml(tools.ustr(que.comment_label)) + """</para></td>
255 <td><para style="answer_right">""" + tools.ustr(tot_res) + """</para></td></tr></blockTable>"""
257 elif que.type in['single_textbox']:
258 cr.execute("select count(id) from survey_response_line where question_id = %s and single_text!=''",(que.id,))
259 rml += """<blockTable colWidths="400.0,100.0" style="Table1">
261 <td> <para style="Standard"> </para></td>
262 <td> <para style="response-bold">Answer Count</para></td>
264 <tr><td><para style="answer"></para></td>
265 <td><para style="answer_right">""" + tools.ustr(cr.fetchone()[0]) + """ </para></td></tr>
268 elif que.type in['comment']:
269 cr.execute("select count(id) from survey_response_line where question_id = %s and comment !=''", (que.id,))
270 rml += """<blockTable colWidths="400.0,100.0" style="Table1">
272 <td> <para style="Standard"> </para></td>
273 <td> <para style="response-bold">Answer Count</para></td>
275 <tr><td><para style="answer"></para></td>
276 <td><para style="answer_right">""" + tools.ustr(cr.fetchone()[0]) + """ </para></td></tr>
279 elif que.type in['rating_scale']:
280 cols_widhts.append(200)
281 for col in range(0,len(que.column_heading_ids) + 2):
282 cols_widhts.append(float(300 / (len(que.column_heading_ids) + 2)))
283 colWidths = ",".join(map(tools.ustr, cols_widhts))
284 matrix_ans = [(0,'')]
286 for col in que.column_heading_ids:
287 if col.title not in matrix_ans:
288 matrix_ans.append((col.id,col.title))
289 rml += """<blockTable colWidths=" """ + colWidths + """ " style="Table1"><tr>"""
290 for mat_col in range(0,len(matrix_ans)):
291 rml += """<td><para style="response">""" + to_xml(tools.ustr(matrix_ans[mat_col][1])) + """</para></td>"""
292 rml += """<td><para style="response-bold">Rating Average</para></td>
293 <td><para style="response-bold">Answer Count</para></td>
296 for ans in que.answer_choice_ids:
297 rml += """<tr><td><para style="answer">""" + to_xml(tools.ustr(ans.answer)) + """</para></td>"""
299 rating_weight_sum = 0
300 for mat_col in range(1, len(matrix_ans)):
301 cr.execute("select count(sra.answer_id) from survey_response_line sr, survey_response_answer sra\
302 where sr.id = sra.response_id and sra.answer_id = %s and sra.column_id ='%s'", (ans.id,matrix_ans[mat_col][0]))
303 tot_res = cr.fetchone()[0]
304 cr.execute("select count(sra.answer_id),sqc.rating_weight from survey_response_line sr, survey_response_answer sra ,\
305 survey_question_column_heading sqc where sr.id = sra.response_id and \
306 sqc.question_id = sr.question_id and sra.answer_id = %s and sqc.title ='%s'\
307 + group by sra.answer_id,sqc.rating_weight", (ans.id,matrix_ans[mat_col][1]))
308 col_weight = cr.fetchone()
312 elif not col_weight[1]:
313 col_weight = (col_weight[0],0)
314 res_count = col_weight[0]
316 if tot_res and res_count:
317 rating_weight_sum += int(col_weight[1]) * tot_res
318 tot_per = round((float(tot_res) * 100) / int(res_count), 2)
323 rml += """<td><para style="answer_bold">""" + tools.ustr(tot_per) + "%(" + tools.ustr(tot_res) + """)</para></td>"""
325 rml += """<td><para style="answer">""" + tools.ustr(tot_per)+"%(" + tools.ustr(tot_res) + """)</para></td>"""
329 percantage = round((float(rating_weight_sum)/res_count), 2)
330 rml += """<td><para style="answer_right">""" + tools.ustr(percantage) + """</para></td>
331 <td><para style="answer_right">""" + tools.ustr(res_count) + """</para></td></tr>"""
332 rml += """</blockTable>"""
334 elif que.type in['matrix_of_drop_down_menus']:
335 for column in que.column_heading_ids:
336 rml += """<blockTable colWidths="500" style="Table1"><tr>
337 <td><para style="answer">""" + to_xml(tools.ustr(column.title)) + """</para></td></tr></blockTable>"""
338 menu_choices = column.menu_choice.split('\n')
340 cols_widhts.append(200)
341 for col in range(0, len(menu_choices) + 1):
342 cols_widhts.append(float(300 / (len(menu_choices) + 1)))
343 colWidths = ",".join(map(tools.ustr, cols_widhts))
344 rml += """<blockTable colWidths=" """ + colWidths + """ " style="Table1"><tr>
345 <td><para style="response"></para></td>"""
347 for menu in menu_choices:
348 rml += """<td><para style="response">""" + to_xml(tools.ustr(menu)) + """</para></td>"""
349 rml += """<td><para style="response-bold">Answer Count</para></td></tr>"""
350 cr.execute("select count(id), sra.answer_id from survey_response_answer sra \
351 where sra.column_id='%s' group by sra.answer_id ", (column.id,))
352 res_count = cr.dictfetchall()
353 cr.execute("select count(sra.id),sra.value_choice, sra.answer_id, sra.column_id from survey_response_answer sra \
354 where sra.column_id='%s' group by sra.value_choice ,sra.answer_id, sra.column_id", (column.id,))
355 calc_percantage = cr.dictfetchall()
357 for ans in que.answer_choice_ids:
358 rml += """<tr><td><para style="answer_right">""" + to_xml(tools.ustr(ans.answer)) + """</para></td>"""
359 for mat_col in range(0, len(menu_choices)):
362 for res in res_count:
363 if res['answer_id'] == ans.id: response = res['count']
364 for per in calc_percantage:
365 if ans.id == per['answer_id'] and menu_choices[mat_col] == per['value_choice']:
369 if calc and response:
370 percantage = round((float(calc)* 100) / response,2)
372 rml += """<td><para style="answer_bold">""" +tools.ustr(percantage)+"% (" + tools.ustr(calc) + """)</para></td>"""
374 rml += """<td><para style="answer">""" +tools.ustr(percantage)+"% (" + tools.ustr(calc) + """)</para></td>"""
377 for res in res_count:
378 if res['answer_id'] == ans.id: response = res['count']
379 rml += """<td><para style="answer_right">""" + tools.ustr(response) + """</para></td></tr>"""
380 rml += """</blockTable>"""
382 elif que.type in['numerical_textboxes']:
383 rml += """<blockTable colWidths="240.0,20,100.0,70,70.0" style="Table1">
385 <td> <para style="Standard"> </para></td>
386 <td> <para style="Standard"> </para></td>
387 <td> <para style="response">Answer Average</para></td>
388 <td> <para style="response">Answer Total</para></td>
389 <td> <para style="response-bold">Answer Count</para></td>
391 for ans in que.answer_choice_ids:
392 cr.execute("select answer from survey_response_answer where answer_id=%s group by answer", (ans.id,))
393 tot_res = cr.dictfetchall()
396 total += int(tot['answer'])
400 per = round((float(total) / len(tot_res)),2)
401 rml+="""<tr><td><para style="answer">""" + to_xml(tools.ustr(ans.answer)) + """</para></td>
402 <td> <para style="Standard"> </para></td>
403 <td> <para style="answer">""" + tools.ustr(per) +"""</para></td>
404 <td><para style="answer">""" + tools.ustr(total) + """</para></td>
405 <td><para style="answer_right">""" + tools.ustr(len(tot_res)) + """</para></td></tr>"""
406 rml+="""</blockTable>"""
408 rml +="""<blockTable colWidths="300,100,100.0" style="Table3">
410 <td><para style="Standard1"></para></td>
411 <td><para style="Standard1">Answered Question</para></td>
412 <td><para style="Standard1">""" + tools.ustr(que.tot_resp) + """</para></td>
415 <td><para style="Standard1"></para></td>
416 <td><para style="Standard1">Skipped Question</para></td>
417 <td><para style="Standard1">""" + tools.ustr(survey.tot_start_survey - que.tot_resp) + """</para></td>
420 rml += """</story>"""
422 rml += """</document>"""
423 report_type = datas.get('report_type', 'pdf')
424 create_doc = self.generators[report_type]
425 self.internal_header=True
426 pdf = create_doc(rml, title=self.title)
428 return (pdf, report_type)
430 survey_analysis('report.survey.analysis', 'survey','','')
432 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: