1 ## -*- coding: utf-8 -*-
2 ##############################################################################
4 # OpenERP, Open Source Management Solution
5 # Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
7 # This program is free software: you can redistribute it and/or modify
8 # it under the terms of the GNU Affero General Public License as
9 # published by the Free Software Foundation, either version 3 of the
10 # License, or (at your option) any later version.
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU Affero General Public License for more details.
17 # You should have received a copy of the GNU Affero General Public License
18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
20 ##############################################################################
23 from lxml import etree
24 from time import strftime
30 from osv import fields
31 from tools import to_xml
32 from tools.translate import _
34 from tools.safe_eval import safe_eval
36 class survey_question_wiz(osv.osv_memory):
37 _name = 'survey.question.wiz'
39 'name': fields.integer('Number'),
42 def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
44 Fields View Get method :- generate the new view and display the survey pages of selected survey.
48 result = super(survey_question_wiz, self).fields_view_get(cr, uid, view_id, \
49 view_type, context, toolbar,submenu)
51 surv_name_wiz = self.pool.get('survey.name.wiz')
52 survey_obj = self.pool.get('survey')
53 page_obj = self.pool.get('survey.page')
54 que_obj = self.pool.get('survey.question')
55 ans_obj = self.pool.get('survey.answer')
56 sur_response_obj = self.pool.get('survey.response')
57 que_col_head = self.pool.get('survey.question.column.heading')
58 user_obj = self.pool.get('res.users')
59 mail_message = self.pool.get('mail.message')
61 if view_type in ['form']:
64 if 'sur_name_id' in context:
65 sur_name_rec = surv_name_wiz.browse(cr, uid, context['sur_name_id'], context=context)
66 elif 'survey_id' in context:
68 'survey_id': context.get('survey_id', False),
74 wiz_id = surv_name_wiz.create(cr, uid, res_data)
75 sur_name_rec = surv_name_wiz.browse(cr, uid, wiz_id, context=context)
76 context.update({'sur_name_id' :wiz_id})
78 if context.has_key('active_id'):
79 context.pop('active_id')
81 survey_id = context.get('survey_id', False)
83 # Try one more time to find it
84 if sur_name_rec and sur_name_rec.survey_id:
85 survey_id = sur_name_rec.survey_id.id
87 # raise osv.except_osv(_('Error!'), _("Cannot locate survey for the question wizard!"))
88 # If this function is called without a survey_id in
89 # its context, it makes no sense to return any view.
90 # Just return the default, empty view for this object,
91 # in order to please random calls to this fn().
92 return super(survey_question_wiz, self).\
93 fields_view_get(cr, uid, view_id=view_id, view_type=view_type, context=context,
94 toolbar=toolbar, submenu=submenu)
95 sur_rec = survey_obj.browse(cr, uid, survey_id, context=context)
96 p_id = map(lambda x:x.id, sur_rec.page_ids)
97 total_pages = len(p_id)
101 if context.get('response_id', False) \
102 and int(context['response_id'][0]) > 0:
105 if not sur_name_rec.page_no + 1 :
106 surv_name_wiz.write(cr, uid, [context['sur_name_id'],], {'store_ans':{}})
108 sur_name_read = surv_name_wiz.browse(cr, uid, context['sur_name_id'], context=context)
109 page_number = int(sur_name_rec.page_no)
110 if sur_name_read.transfer or not sur_name_rec.page_no + 1:
111 surv_name_wiz.write(cr, uid, [context['sur_name_id']], {'transfer':False})
114 if sur_name_read.page == "next" or sur_name_rec.page_no == -1:
115 if total_pages > sur_name_rec.page_no + 1:
116 if ((context.has_key('active') and not context.get('active', False)) \
117 or not context.has_key('active')) and not sur_name_rec.page_no + 1:
118 if sur_rec.state != "open" :
119 raise osv.except_osv(_('Warning !'),_("You can not answer because the survey is not open"))
120 cr.execute('select count(id) from survey_history where user_id=%s\
121 and survey_id=%s', (uid,survey_id))
122 res = cr.fetchone()[0]
123 user_limit = survey_obj.browse(cr, uid, survey_id)
124 user_limit = user_limit.response_user
125 if user_limit and res >= user_limit:
126 raise osv.except_osv(_('Warning !'),_("You can not answer this survey more than %s times") % (user_limit))
128 if sur_rec.max_response_limit and sur_rec.max_response_limit <= sur_rec.tot_start_survey and not sur_name_rec.page_no + 1:
129 survey_obj.write(cr, uid, survey_id, {'state':'close', 'date_close':strftime("%Y-%m-%d %H:%M:%S")})
131 p_id = p_id[sur_name_rec.page_no + 1]
132 surv_name_wiz.write(cr, uid, [context['sur_name_id'],], {'page_no' : sur_name_rec.page_no + 1})
135 if sur_name_rec.page_no > - 1:
138 if sur_name_rec.page_no != 0:
139 p_id = p_id[sur_name_rec.page_no - 1]
140 surv_name_wiz.write(cr, uid, [context['sur_name_id'],],\
141 {'page_no' : sur_name_rec.page_no - 1})
145 if sur_name_rec.page_no > 1:
148 pag_rec = page_obj.browse(cr, uid, p_id, context=context)
149 xml_form = etree.Element('form', {'string': tools.ustr(pag_rec.title)})
150 xml_group = etree.SubElement(xml_form, 'group', {'col': '1', 'colspan': '4'})
151 if context.has_key('response_id') and context.get('response_id', False) \
152 and int(context.get('response_id',0)[0]) > 0:
153 # TODO: l10n, cleanup this code to make it readable. Or template?
154 xml_group = etree.SubElement(xml_form, 'group', {'col': '40', 'colspan': '4'})
155 record = sur_response_obj.browse(cr, uid, context['response_id'][context['response_no']])
156 etree.SubElement(xml_group, 'label', {'string': to_xml(tools.ustr('Answer Of :- ' + record.user_id.name + ', Date :- ' + record.date_create.split('.')[0] )), 'align':"0.0"})
157 etree.SubElement(xml_group, 'label', {'string': to_xml(tools.ustr(" Answer :- " + str(context.get('response_no',0) + 1) +"/" + str(len(context.get('response_id',0))) )), 'align':"0.0"})
158 if context.get('response_no',0) > 0:
159 etree.SubElement(xml_group, 'button', {'colspan':"1",'icon':"gtk-go-back",'name':"action_forward_previous",'string': tools.ustr("Previous Answer"),'type':"object"})
160 if context.get('response_no',0) + 1 < len(context.get('response_id',0)):
161 etree.SubElement(xml_group, 'button', {'colspan':"1",'icon': "gtk-go-forward", 'name':"action_forward_next",'string': tools.ustr("Next Answer") ,'type':"object",'context' : tools.ustr(context)})
164 fields["wizardid_" + str(wiz_id)] = {'type':'char', 'size' : 255, 'string':"", 'views':{}}
165 etree.SubElement(xml_form, 'field', {'invisible':'1','name': "wizardid_" + str(wiz_id),'default':str(lambda *a: 0)})
168 xml_group = etree.SubElement(xml_form, 'group', {'col': '1', 'colspan': '4'})
169 for que_test in pag_rec.note.split('\n'):
170 etree.SubElement(xml_group, 'label', {'string': to_xml(tools.ustr(que_test)), 'align':"0.0"})
171 que_ids = pag_rec.question_ids
176 que_rec = que_obj.browse(cr, uid, que.id, context=context)
177 descriptive_text = ""
178 separator_string = tools.ustr(qu_no) + "." + tools.ustr(que_rec.question)
179 if ((context.has_key('active') and not context.get('active',False)) or not context.has_key('active')) and que_rec.is_require_answer:
183 xml_group = etree.SubElement(xml_form, 'group', {'col': '2', 'colspan': '4'})
185 if context.has_key('active') and context.get('active',False) and \
186 context.has_key('edit'):
187 xml_group = etree.SubElement(xml_form, 'group', {'col': '1', 'colspan': '2'})
188 etree.SubElement(xml_group, 'separator', {'string': star+to_xml(separator_string), 'colspan': '3'})
189 xml_group1 = etree.SubElement(xml_form, 'group', {'col': '2', 'colspan': '2'})
190 context.update({'question_id' : tools.ustr(que.id),'page_number': sur_name_rec.page_no , 'transfer' : sur_name_read.transfer, 'page_id' : p_id})
191 etree.SubElement(xml_group1, 'button', {'string':'','icon': "gtk-edit", 'type' :'object', 'name':"action_edit_question", 'context' : tools.ustr(context)})
192 etree.SubElement(xml_group1, 'button', {'string':'','icon': "gtk-delete", 'type' :'object','name':"action_delete_question", 'context' : tools.ustr(context)})
194 xml_group = etree.SubElement(xml_form, 'group', {'col': '1', 'colspan': '4'})
195 etree.SubElement(xml_group, 'separator', {'string': star+to_xml(separator_string), 'colspan': '4'})
197 ans_ids = que_rec.answer_choice_ids
198 xml_group = etree.SubElement(xml_form, 'group', {'col': '1', 'colspan': '4'})
200 if que_rec.type == 'multiple_choice_only_one_ans':
203 selection.append((tools.ustr(ans.id), ans.answer))
204 xml_group = etree.SubElement(xml_group, 'group', {'col': '2', 'colspan': '2'})
205 etree.SubElement(xml_group, 'field', {'readonly':str(readonly), 'name': tools.ustr(que.id) + "_selection"})
206 fields[tools.ustr(que.id) + "_selection"] = {'type':'selection', 'selection' :selection, 'string':"Answer"}
208 elif que_rec.type == 'multiple_choice_multiple_ans':
209 xml_group = etree.SubElement(xml_group, 'group', {'col': '4', 'colspan': '4'})
211 etree.SubElement(xml_group, 'field', {'readonly':str(readonly), 'name': tools.ustr(que.id) + "_" + tools.ustr(ans.id)})
212 fields[tools.ustr(que.id) + "_" + tools.ustr(ans.id)] = {'type':'boolean', 'string':ans.answer}
214 elif que_rec.type in ['matrix_of_choices_only_one_ans', 'rating_scale']:
215 if que_rec.comment_column:
221 xml_group = etree.SubElement(xml_group, 'group', {'col': tools.ustr(col), 'colspan': tools.ustr(colspan)})
223 etree.SubElement(xml_group, 'newline')
224 etree.SubElement(xml_group, 'field', {'readonly': str(readonly), 'name': tools.ustr(que.id) + "_selection_" + tools.ustr(row.id),'string':to_xml(tools.ustr(row.answer))})
225 selection = [('','')]
226 for col in que_rec.column_heading_ids:
227 selection.append((str(col.id), col.title))
228 fields[tools.ustr(que.id) + "_selection_" + tools.ustr(row.id)] = {'type':'selection', 'selection' : selection, 'string': "Answer"}
229 if que_rec.comment_column:
230 fields[tools.ustr(que.id) + "_commentcolumn_"+tools.ustr(row.id) + "_field"] = {'type':'char', 'size' : 255, 'string':tools.ustr(que_rec.column_name), 'views':{}}
231 etree.SubElement(xml_group, 'field', {'readonly' :str(readonly), 'name': tools.ustr(que.id) + "_commentcolumn_"+tools.ustr(row.id)+ "_field"})
233 elif que_rec.type == 'matrix_of_choices_only_multi_ans':
234 xml_group = etree.SubElement(xml_group, 'group', {'col': str(len(que_rec.column_heading_ids) + 1), 'colspan': '4'})
235 etree.SubElement(xml_group, 'separator', {'string': '.','colspan': '1'})
236 for col in que_rec.column_heading_ids:
237 etree.SubElement(xml_group, 'separator', {'string': tools.ustr(col.title),'colspan': '1'})
239 etree.SubElement(xml_group, 'label', {'string': to_xml(tools.ustr(row.answer)) +' :-', 'align': '0.0'})
240 for col in que_col_head.browse(cr, uid, [head.id for head in que_rec.column_heading_ids]):
241 etree.SubElement(xml_group, 'field', {'readonly' :str(readonly), 'name': tools.ustr(que.id) + "_" + tools.ustr(row.id) + "_" + tools.ustr(col.id), 'nolabel':"1"})
242 fields[tools.ustr(que.id) + "_" + tools.ustr(row.id) + "_" + tools.ustr(col.id)] = {'type':'boolean', 'string': col.title}
244 elif que_rec.type == 'matrix_of_drop_down_menus':
245 xml_group = etree.SubElement(xml_group, 'group', {'col': str(len(que_rec.column_heading_ids) + 1), 'colspan': '4'})
246 etree.SubElement(xml_group, 'separator', {'string': '.','colspan': '1'})
247 for col in que_rec.column_heading_ids:
248 etree.SubElement(xml_group, 'separator', {'string': tools.ustr(col.title),'colspan': '1'})
250 etree.SubElement(xml_group, 'label', {'string': to_xml(tools.ustr(row.answer))+' :-', 'align': '0.0'})
251 for col in que_rec.column_heading_ids:
254 for item in col.menu_choice.split('\n'):
255 if item and not item.strip() == '': selection.append((item ,item))
256 etree.SubElement(xml_group, 'field', {'readonly' :str(readonly), 'name': tools.ustr(que.id) + "_" + tools.ustr(row.id) + "_" + tools.ustr(col.id),'nolabel':'1'})
257 fields[tools.ustr(que.id) + "_" + tools.ustr(row.id) + "_" + tools.ustr(col.id)] = {'type':'selection', 'string': col.title, 'selection':selection}
259 elif que_rec.type == 'multiple_textboxes':
260 xml_group = etree.SubElement(xml_group, 'group', {'col': '4', 'colspan': '4'})
262 if que_rec.is_validation_require:
263 if que_rec.validation_type in ['must_be_whole_number']:
265 elif que_rec.validation_type in ['must_be_decimal_number']:
267 elif que_rec.validation_type in ['must_be_date']:
270 etree.SubElement(xml_group, 'field', {'readonly': str(readonly), 'width':"300",'colspan': '1','name': tools.ustr(que.id) + "_" + tools.ustr(ans.id) + "_multi"})
272 fields[tools.ustr(que.id) + "_" + tools.ustr(ans.id) + "_multi"] = {'type':'char', 'size':255, 'string':ans.answer}
274 fields[tools.ustr(que.id) + "_" + tools.ustr(ans.id) + "_multi"] = {'type': str(type), 'string':ans.answer}
276 elif que_rec.type == 'numerical_textboxes':
277 xml_group = etree.SubElement(xml_group, 'group', {'col': '4', 'colspan': '4'})
279 etree.SubElement(xml_group, 'field', {'readonly': str(readonly), 'width':"300",'colspan': '1','name': tools.ustr(que.id) + "_" + tools.ustr(ans.id) + "_numeric"})
280 fields[tools.ustr(que.id) + "_" + tools.ustr(ans.id) + "_numeric"] = {'type':'integer', 'string':ans.answer}
282 elif que_rec.type == 'date':
283 xml_group = etree.SubElement(xml_group, 'group', {'col': '4', 'colspan': '4'})
285 etree.SubElement(xml_group, 'field', {'readonly': str(readonly), 'width':"300",'colspan': '1','name': tools.ustr(que.id) + "_" + tools.ustr(ans.id)})
286 fields[tools.ustr(que.id) + "_" + tools.ustr(ans.id)] = {'type':'date', 'string':ans.answer}
288 elif que_rec.type == 'date_and_time':
289 xml_group = etree.SubElement(xml_group, 'group', {'col': '4', 'colspan': '4'})
291 etree.SubElement(xml_group, 'field', {'readonly': str(readonly), 'width':"300",'colspan': '1','name': tools.ustr(que.id) + "_" + tools.ustr(ans.id)})
292 fields[tools.ustr(que.id) + "_" + tools.ustr(ans.id)] = {'type':'datetime', 'string':ans.answer}
294 elif que_rec.type == 'descriptive_text':
295 if que_rec.descriptive_text:
296 for que_test in que_rec.descriptive_text.split('\n'):
297 etree.SubElement(xml_group, 'label', {'string': to_xml(tools.ustr(que_test)), 'align':"0.0"})
299 elif que_rec.type == 'single_textbox':
300 etree.SubElement(xml_group, 'field', {'readonly' :str(readonly), 'name': tools.ustr(que.id) + "_single", 'nolabel':"1" ,'colspan':"4"})
301 fields[tools.ustr(que.id) + "_single"] = {'type':'char', 'size': 255, 'string':"single_textbox", 'views':{}}
303 elif que_rec.type == 'comment':
304 etree.SubElement(xml_group, 'field', {'readonly' :str(readonly), 'name': tools.ustr(que.id) + "_comment", 'nolabel':"1" ,'colspan':"4"})
305 fields[tools.ustr(que.id) + "_comment"] = {'type':'text', 'string':"Comment/Eassy Box", 'views':{}}
307 elif que_rec.type == 'table':
308 xml_group = etree.SubElement(xml_group, 'group', {'col': str(len(que_rec.column_heading_ids)), 'colspan': '4'})
309 for col in que_rec.column_heading_ids:
310 etree.SubElement(xml_group, 'separator', {'string': tools.ustr(col.title),'colspan': '1'})
311 for row in range(0,que_rec.no_of_rows):
312 for col in que_rec.column_heading_ids:
313 etree.SubElement(xml_group, 'field', {'readonly' :str(readonly), 'name': tools.ustr(que.id) + "_table_" + tools.ustr(col.id) +"_"+ tools.ustr(row), 'nolabel':"1"})
314 fields[tools.ustr(que.id) + "_table_" + tools.ustr(col.id) +"_"+ tools.ustr(row)] = {'type':'char','size':255,'views':{}}
316 elif que_rec.type == 'multiple_textboxes_diff_type':
317 xml_group = etree.SubElement(xml_group, 'group', {'col': '4', 'colspan': '4'})
319 if ans.type == "email" :
320 fields[tools.ustr(que.id) + "_" + tools.ustr(ans.id) + "_multi"] = {'type':'char', 'size':255, 'string':ans.answer}
321 etree.SubElement(xml_group, 'field', {'readonly': str(readonly), 'widget':'email','width':"300",'colspan': '1','name': tools.ustr(que.id) + "_" + tools.ustr(ans.id) + "_multi"})
323 etree.SubElement(xml_group, 'field', {'readonly': str(readonly), 'width':"300",'colspan': '1','name': tools.ustr(que.id) + "_" + tools.ustr(ans.id) + "_multi"})
324 if ans.type == "char" :
325 fields[tools.ustr(que.id) + "_" + tools.ustr(ans.id) + "_multi"] = {'type':'char', 'size':255, 'string':ans.answer}
326 elif ans.type in ['integer','float','date','datetime']:
327 fields[tools.ustr(que.id) + "_" + tools.ustr(ans.id) + "_multi"] = {'type': str(ans.type), 'string':ans.answer}
331 for item in ans.menu_choice.split('\n'):
332 if item and not item.strip() == '': selection.append((item ,item))
333 fields[tools.ustr(que.id) + "_" + tools.ustr(ans.id) + "_multi"] = {'type':'selection', 'selection' : selection, 'string':ans.answer}
335 if que_rec.type in ['multiple_choice_only_one_ans', 'multiple_choice_multiple_ans', 'matrix_of_choices_only_one_ans', 'matrix_of_choices_only_multi_ans', 'matrix_of_drop_down_menus', 'rating_scale'] and que_rec.is_comment_require:
336 if que_rec.type in ['multiple_choice_only_one_ans', 'multiple_choice_multiple_ans'] and que_rec.comment_field_type in ['char','text'] and que_rec.make_comment_field:
337 etree.SubElement(xml_group, 'field', {'readonly' :str(readonly), 'name': tools.ustr(que.id) + "_otherfield", 'colspan':"4"})
338 fields[tools.ustr(que.id) + "_otherfield"] = {'type':'boolean', 'string':que_rec.comment_label, 'views':{}}
339 if que_rec.comment_field_type == 'char':
340 etree.SubElement(xml_group, 'field', {'readonly' :str(readonly), 'name': tools.ustr(que.id) + "_other", 'nolabel':"1" ,'colspan':"4"})
341 fields[tools.ustr(que.id) + "_other"] = {'type': 'char', 'string': '', 'size':255, 'views':{}}
342 elif que_rec.comment_field_type == 'text':
343 etree.SubElement(xml_group, 'field', {'readonly' :str(readonly), 'name': tools.ustr(que.id) + "_other", 'nolabel':"1" ,'colspan':"4"})
344 fields[tools.ustr(que.id) + "_other"] = {'type': 'text', 'string': '', 'views':{}}
346 if que_rec.comment_field_type == 'char':
347 etree.SubElement(xml_group, 'label', {'string': to_xml(tools.ustr(que_rec.comment_label)),'colspan':"4"})
348 etree.SubElement(xml_group, 'field', {'readonly' :str(readonly), 'name': tools.ustr(que.id) + "_other", 'nolabel':"1" ,'colspan':"4"})
349 fields[tools.ustr(que.id) + "_other"] = {'type': 'char', 'string': '', 'size':255, 'views':{}}
350 elif que_rec.comment_field_type == 'text':
351 etree.SubElement(xml_group, 'label', {'string': to_xml(tools.ustr(que_rec.comment_label)),'colspan':"4"})
352 etree.SubElement(xml_group, 'field', {'readonly' :str(readonly), 'name': tools.ustr(que.id) + "_other", 'nolabel':"1" ,'colspan':"4"})
353 fields[tools.ustr(que.id) + "_other"] = {'type': 'text', 'string': '', 'views':{}}
355 etree.SubElement(xml_form, 'separator', {'colspan': '4'})
356 xml_group = etree.SubElement(xml_form, 'group', {'col': '6', 'colspan': '4'})
357 etree.SubElement(xml_group, 'field', {'name': 'progress_bar_' + tools.ustr(page_number) , 'widget':'progressbar'})
358 fields['progress_bar_' + tools.ustr(page_number)] = {'type':'float', 'string':"Progress", 'views':{}}
359 etree.SubElement(xml_group, 'label', {'string': tools.ustr(page_number+ 1) + "/" + tools.ustr(total_pages)})
360 etree.SubElement(xml_group, 'button', {'icon': "gtk-cancel", 'special': "cancel",'string':"Cancel"})
363 etree.SubElement(xml_group, 'button', {'colspan':"1",'icon':"gtk-go-back",'name':"action_previous",'string':"Previous",'type':"object"})
365 if int(page_number) + 1 == total_pages:
368 if context.has_key('active') and context.get('active',False) and int(page_number) + 1 == total_pages and context.has_key('response_id') and context.has_key('response_no') and context.get('response_no',0) + 1 == len(context.get('response_id',0)):
369 etree.SubElement(xml_group, 'button', {'icon': "gtk-go-forward", 'special' : 'cancel','string': tools.ustr("Done") ,'context' : tools.ustr(context)})
370 elif context.has_key('active') and context.get('active', False) and int(page_number) + 1 == total_pages and context.has_key('response_id'):
371 etree.SubElement(xml_group, 'button', {'icon': "gtk-go-forward", 'name':"action_forward_next",'string': tools.ustr("Next Answer") ,'type':"object",'context' : tools.ustr(context)})
372 elif context.has_key('active') and context.get('active',False) and int(page_number) + 1 == total_pages:
373 etree.SubElement(xml_group, 'button', {'icon': "gtk-go-forward", 'special': "cancel", 'string' : 'Done', 'context' : tools.ustr(context)})
375 etree.SubElement(xml_group, 'button', {'icon': "gtk-go-forward", 'name':"action_next",'string': tools.ustr(but_string) ,'type':"object",'context' : tools.ustr(context)})
377 if context.has_key('active') and context.get('active',False) and context.has_key('edit'):
378 etree.SubElement(xml_form, 'separator', {'string' : '','colspan': '4'})
379 context.update({'page_id' : tools.ustr(p_id),'page_number' : sur_name_rec.page_no , 'transfer' : sur_name_read.transfer})
380 xml_group3 = etree.SubElement(xml_form, 'group', {'col': '4', 'colspan': '4'})
381 etree.SubElement(xml_group3, 'button', {'string' :'Add Page','icon': "gtk-new", 'type' :'object','name':"action_new_page", 'context' : tools.ustr(context)})
382 etree.SubElement(xml_group3, 'button', {'string' :'Edit Page','icon': "gtk-edit", 'type' :'object','name':"action_edit_page", 'context' : tools.ustr(context)})
383 etree.SubElement(xml_group3, 'button', {'string' :'Delete Page','icon': "gtk-delete", 'type' :'object','name':"action_delete_page", 'context' : tools.ustr(context)})
384 etree.SubElement(xml_group3, 'button', {'string' :'Add Question','icon': "gtk-new", 'type' :'object','name':"action_new_question", 'context' : tools.ustr(context)})
386 root = xml_form.getroottree()
387 result['arch'] = etree.tostring(root)
388 result['fields'] = fields
389 result['context'] = context
391 survey_obj.write(cr, uid, survey_id, {'tot_comp_survey' : sur_rec.tot_comp_survey + 1})
392 sur_response_obj.write(cr, uid, [sur_name_read.response], {'state' : 'done'})
394 # mark the survey request as done; call 'survey_req_done' on its actual model
395 survey_req_obj = self.pool.get(context.get('active_model'))
396 if survey_req_obj and hasattr(survey_req_obj, 'survey_req_done'):
397 survey_req_obj.survey_req_done(cr, uid, context.get('active_ids', []), context=context)
399 if sur_rec.send_response:
400 survey_data = survey_obj.browse(cr, uid, survey_id)
401 response_id = surv_name_wiz.read(cr, uid, context.get('sur_name_id',False))['response']
402 context.update({'response_id':response_id})
403 report = self.create_report(cr, uid, [survey_id], 'report.survey.browse.response', survey_data.title,context)
405 file = open(addons.get_module_resource('survey', 'report') + survey_data.title + ".pdf")
408 line = file.readline()
413 attachments[survey_data.title + ".pdf"] = file_data
415 os.remove(addons.get_module_resource('survey', 'report') + survey_data.title + ".pdf")
417 user_email = user_obj.browse(cr, uid, uid, context).user_email
418 resp_email = survey_data.responsible_id and survey_data.responsible_id.user_email or False
420 if user_email and resp_email:
421 user_name = user_obj.browse(cr, uid, uid, context=context).name
422 mail = "Hello " + survey_data.responsible_id.name + ",\n\n " + str(user_name) + " has given the Response Of " + survey_data.title + " Survey.\nThe Response has been attached herewith.\n\n Thanks."
423 mail_message.schedule_with_attach(cr, uid, user_email, [resp_email], "Survey Answer Of " + str(user_name) , mail, attachments=attachments, context=context)
425 xml_form = etree.Element('form', {'string': _('Complete Survey Answer')})
426 etree.SubElement(xml_form, 'separator', {'string': 'Complete Survey', 'colspan': "4"})
427 etree.SubElement(xml_form, 'label', {'string': 'Thanks for your Answer'})
428 etree.SubElement(xml_form, 'newline')
429 etree.SubElement(xml_form, 'button', {'icon': "gtk-go-forward", 'special':"cancel",'string':"OK",'colspan':"2"})
430 root = xml_form.getroottree()
431 result['arch'] = etree.tostring(root)
432 result['fields'] = {}
433 result['context'] = context
436 def create_report(self, cr, uid, res_ids, report_name=False, file_name=False, context=None):
438 If any user give answer of survey then last create report of this answer and if 'E-mail Notification on Answer' set True in survey then send mail on responsible person of this survey and attach survey answer report in pdf format.
440 if not report_name or not res_ids:
441 return (False, Exception('Report name and Resources ids are required !!!'))
444 service = netsvc.LocalService(report_name);
445 (result, format) = service.create(cr, uid, res_ids, {}, context)
446 ret_file_name = addons.get_module_resource('survey', 'report') + file_name + '.pdf'
447 fp = open(ret_file_name, 'wb+');
451 # hr.applicant: if survey answered directly in system: attach report to applicant
452 if context.get('active_model') == 'hr.applicant':
453 result = base64.b64encode(result)
454 file_name = file_name + '.pdf'
455 ir_attachment = self.pool.get('ir.attachment').create(cr, uid,
458 'datas_fname': file_name,
459 'res_model': context.get('active_model'),
460 'res_id': context.get('active_ids')[0]},
464 return (False, str(e))
466 return (True, ret_file_name)
468 def default_get(self, cr, uid, fields_list, context=None):
470 Assign Default value in particular field. If Browse Answers wizard run then read the value into database and Assigne to a particular fields.
475 for field in fields_list:
476 if field.split('_')[0] == 'progress':
477 tot_page_id = self.pool.get('survey').browse(cr, uid, context.get('survey_id',False))
478 tot_per = (float(100) * (int(field.split('_')[2]) + 1) / len(tot_page_id.page_ids))
479 value[field] = tot_per
480 response_obj = self.pool.get('survey.response')
481 surv_name_wiz = self.pool.get('survey.name.wiz')
483 if context.has_key('response_id') and context.get('response_id') and int(context['response_id'][0]) > 0:
484 data = super(survey_question_wiz, self).default_get(cr, uid, fields_list, context)
485 response_ans = response_obj.browse(cr, uid, context['response_id'][context['response_no']])
488 for que in response_ans.question_ids:
489 for field in fields_list:
490 if field.split('_')[0] != "progress" and field.split('_')[0] == str(que.question_id.id):
491 if que.response_answer_ids and len(field.split('_')) == 4 and field.split('_')[1] == "commentcolumn" and field.split('_')[3] == "field":
492 for ans in que.response_answer_ids:
493 if str(field.split('_')[2]) == str(ans.answer_id.id):
494 value[field] = ans.comment_field
496 if que.response_table_ids and len(field.split('_')) == 4 and field.split('_')[1] == "table":
497 for ans in que.response_table_ids:
498 if str(field.split('_')[2]) == str(ans.column_id.id) and str(field.split('_')[3]) == str(ans.name):
499 value[field] = ans.value
501 if que.comment and (field.split('_')[1] == "comment" or field.split('_')[1] == "other"):
502 value[field] = str(que.comment)
504 elif que.single_text and field.split('_')[1] == "single":
505 value[field] = str(que.single_text)
507 elif que.response_answer_ids and len(field.split('_')) == 3 and field.split('_')[1] == "selection":
508 for ans in que.response_answer_ids:
509 if str(field.split('_')[2]) == str( ans.answer_id.id):
510 value[field] = str(ans.column_id.id)
512 elif que.response_answer_ids and len(field.split('_')) == 2 and field.split('_')[1] == "selection":
513 value[field] = str(que.response_answer_ids[0].answer_id.id)
515 elif que.response_answer_ids and len(field.split('_')) == 3 and field.split('_')[2] != "multi" and field.split('_')[2] != "numeric":
516 for ans in que.response_answer_ids:
517 if str(field.split('_')[1]) == str( ans.answer_id.id) and str(field.split('_')[2]) == str(ans.column_id.id):
519 value[field] = ans.value_choice
524 for ans in que.response_answer_ids:
525 if str(field.split('_')[1]) == str( ans.answer_id.id):
526 value[field] = ans.answer
529 if not context.has_key('sur_name_id'):
531 if context.has_key('active') and context.get('active',False):
534 sur_name_read = surv_name_wiz.read(cr, uid, context.get('sur_name_id',False))
537 for key,val in safe_eval(sur_name_read.get('store_ans',"{}")).items():
538 for field in fields_list:
539 if field in list(val):
540 value[field] = val[field]
544 def create(self, cr, uid, vals, context=None):
546 Create the Answer of survey and store in survey.response object, and if set validation of question then check the value of question if value is wrong then raise the exception.
548 if context is None: context = {}
550 survey_question_wiz_id = super(survey_question_wiz,self).create(cr, uid, {'name': vals.get('name')}, context=context)
551 if context.has_key('active') and context.get('active',False):
552 return survey_question_wiz_id
554 for key,val in vals.items():
555 if key.split('_')[0] == "progress":
557 if not context.has_key('sur_name_id') and key.split('_')[0] == "wizardid":
558 context.update({'sur_name_id': int(key.split('_')[1])})
563 surv_name_wiz = self.pool.get('survey.name.wiz')
564 surv_all_resp_obj = self.pool.get('survey.response')
565 surv_tbl_column_obj = self.pool.get('survey.tbl.column.heading')
566 survey_obj = self.pool.get('survey')
567 resp_obj = self.pool.get('survey.response.line')
568 res_ans_obj = self.pool.get('survey.response.answer')
569 que_obj = self.pool.get('survey.question')
570 sur_name_read = surv_name_wiz.read(cr, uid, context.get('sur_name_id',False), [])
573 if not sur_name_read['response']:
574 response_id = surv_all_resp_obj.create(cr, uid, {'response_type':'link', 'user_id':uid, 'date_create':datetime.datetime.now(), 'survey_id' : context['survey_id']})
575 surv_name_wiz.write(cr, uid, [context.get('sur_name_id', False)], {'response' : tools.ustr(response_id)})
577 response_id = int(sur_name_read['response'])
579 if response_id not in surv_all_resp_obj.search(cr, uid, []):
580 response_id = surv_all_resp_obj.create(cr, uid, {'response_type':'link', 'user_id':uid, 'date_create':datetime.datetime.now(), 'survey_id' : context.get('survey_id',False)})
581 surv_name_wiz.write(cr, uid, [context.get('sur_name_id',False)], {'response' : tools.ustr(response_id)})
583 #click first time on next button then increemnet on total start suvey
584 if not safe_eval(sur_name_read['store_ans']):
585 his_id = self.pool.get('survey.history').create(cr, uid, {'user_id': uid, \
586 'date': strftime('%Y-%m-%d %H:%M:%S'), 'survey_id': sur_name_read['survey_id'][0]})
587 survey_id = sur_name_read['survey_id'][0]
588 sur_rec = survey_obj.read(cr, uid, survey_id)
589 survey_obj.write(cr, uid, survey_id, {'tot_start_survey' : sur_rec['tot_start_survey'] + 1})
590 if context.has_key('cur_id'):
591 if context.has_key('request') and context.get('request',False):
592 self.pool.get(context.get('object',False)).write(cr, uid, [int(context.get('cur_id',False))], {'response' : response_id})
593 self.pool.get(context.get('object',False)).survey_req_done(cr, uid, [int(context.get('cur_id'))], context)
595 self.pool.get(context.get('object',False)).write(cr, uid, [int(context.get('cur_id',False))], {'response' : response_id})
596 if sur_name_read['store_ans'] and type(sur_name_read['store_ans']) == dict:
597 for key,val in sur_name_read['store_ans'].items():
599 if field.split('_')[0] == val['question_id']:
601 click_update.append(key)
604 sur_name_read['store_ans'] = {}
608 for key, val in vals.items():
609 que_id = key.split('_')[0]
610 if que_id not in que_li:
611 que_li.append(que_id)
612 que_rec = que_obj.read(cr, uid, [int(que_id)], [])[0]
614 'question_id': que_id,
615 'date_create': datetime.datetime.now(),
617 'response_id': response_id
619 resp_id = resp_obj.create(cr, uid, res_data)
620 resp_id_list.append(resp_id)
621 sur_name_read['store_ans'].update({resp_id:{'question_id':que_id}})
622 surv_name_wiz.write(cr, uid, [context.get('sur_name_id',False)], {'store_ans':sur_name_read['store_ans']})
627 comment_field = False
628 comment_value = False
631 for key1, val1 in vals.items():
632 if val1 and key1.split('_')[1] == "table" and key1.split('_')[0] == que_id:
633 surv_tbl_column_obj.create(cr, uid, {'response_table_id' : resp_id,'column_id':key1.split('_')[2], 'name':key1.split('_')[3], 'value' : val1})
634 sur_name_read['store_ans'][resp_id].update({key1:val1})
637 elif val1 and key1.split('_')[1] == "otherfield" and key1.split('_')[0] == que_id:
639 sur_name_read['store_ans'][resp_id].update({key1:val1})
641 surv_name_wiz.write(cr, uid, [context.get('sur_name_id',False)], {'store_ans':sur_name_read['store_ans']})
644 elif val1 and key1.split('_')[1] == "selection" and key1.split('_')[0] == que_id:
645 if len(key1.split('_')) > 2:
646 ans_create_id = res_ans_obj.create(cr, uid, {'response_id':resp_id, 'answer_id':key1.split('_')[-1], 'column_id' : val1})
647 selected_value.append(val1)
648 response_list.append(str(ans_create_id) + "_" + str(key1.split('_')[-1]))
650 ans_create_id = res_ans_obj.create(cr, uid, {'response_id':resp_id, 'answer_id':val1})
651 sur_name_read['store_ans'][resp_id].update({key1:val1})
654 elif key1.split('_')[1] == "other" and key1.split('_')[0] == que_id:
659 if que_rec['is_comment_require'] and que_rec['comment_valid_type'] == 'must_be_specific_length':
660 if (not val1 and que_rec['comment_minimum_no']) or len(val1) < que_rec['comment_minimum_no'] or len(val1) > que_rec['comment_maximum_no']:
662 elif que_rec['is_comment_require'] and que_rec['comment_valid_type'] in ['must_be_whole_number', 'must_be_decimal_number', 'must_be_date']:
665 if que_rec['comment_valid_type'] == 'must_be_whole_number':
667 if value < que_rec['comment_minimum_no'] or value > que_rec['comment_maximum_no']:
669 elif que_rec['comment_valid_type'] == 'must_be_decimal_number':
671 if value < que_rec['comment_minimum_float'] or value > que_rec['comment_maximum_float']:
673 elif que_rec['comment_valid_type'] == 'must_be_date':
674 value = datetime.datetime.strptime(val1, "%Y-%m-%d")
675 if value < datetime.datetime.strptime(que_rec['comment_minimum_date'], "%Y-%m-%d") or value > datetime.datetime.strptime(que_rec['comment_maximum_date'], "%Y-%m-%d"):
679 elif que_rec['is_comment_require'] and que_rec['comment_valid_type'] == 'must_be_email_address':
681 if re.match("^[a-zA-Z0-9._%-+]+@[a-zA-Z0-9._%-]+.[a-zA-Z]{2,6}$", val1) == None:
684 for res in resp_id_list:
685 sur_name_read['store_ans'].pop(res)
686 raise osv.except_osv(_('Warning !'), "'" + que_rec['question'] + "' \n" + tools.ustr(que_rec['comment_valid_err_msg']))
688 resp_obj.write(cr, uid, resp_id, {'comment':val1})
689 sur_name_read['store_ans'][resp_id].update({key1:val1})
691 elif val1 and key1.split('_')[1] == "comment" and key1.split('_')[0] == que_id:
692 resp_obj.write(cr, uid, resp_id, {'comment':val1})
693 sur_name_read['store_ans'][resp_id].update({key1:val1})
696 elif val1 and key1.split('_')[0] == que_id and (key1.split('_')[1] == "single" or (len(key1.split('_')) > 2 and key1.split('_')[2] == 'multi')):
698 if que_rec['is_validation_require'] and que_rec['validation_type'] == 'must_be_specific_length':
699 if (not val1 and que_rec['validation_minimum_no']) or len(val1) < que_rec['validation_minimum_no'] or len(val1) > que_rec['validation_maximum_no']:
701 elif que_rec['is_validation_require'] and que_rec['validation_type'] in ['must_be_whole_number', 'must_be_decimal_number', 'must_be_date']:
704 if que_rec['validation_type'] == 'must_be_whole_number':
706 if value < que_rec['validation_minimum_no'] or value > que_rec['validation_maximum_no']:
708 elif que_rec['validation_type'] == 'must_be_decimal_number':
710 if value < que_rec['validation_minimum_float'] or value > que_rec['validation_maximum_float']:
712 elif que_rec['validation_type'] == 'must_be_date':
713 value = datetime.datetime.strptime(val1, "%Y-%m-%d")
714 if value < datetime.datetime.strptime(que_rec['validation_minimum_date'], "%Y-%m-%d") or value > datetime.datetime.strptime(que_rec['validation_maximum_date'], "%Y-%m-%d"):
718 elif que_rec['is_validation_require'] and que_rec['validation_type'] == 'must_be_email_address':
720 if re.match("^[a-zA-Z0-9._%-+]+@[a-zA-Z0-9._%-]+.[a-zA-Z]{2,6}$", val1) == None:
723 for res in resp_id_list:
724 sur_name_read['store_ans'].pop(res)
725 raise osv.except_osv(_('Warning !'), "'" + que_rec['question'] + "' \n" + tools.ustr(que_rec['validation_valid_err_msg']))
727 if key1.split('_')[1] == "single" :
728 resp_obj.write(cr, uid, resp_id, {'single_text':val1})
730 ans_create_id = res_ans_obj.create(cr, uid, {'response_id':resp_id, 'answer_id':key1.split('_')[1], 'answer' : val1})
732 sur_name_read['store_ans'][resp_id].update({key1:val1})
735 elif val1 and que_id == key1.split('_')[0] and len(key1.split('_')) > 2 and key1.split('_')[2] == 'numeric':
738 numeric_sum += int(val1)
739 ans_create_id = res_ans_obj.create(cr, uid, {'response_id':resp_id, 'answer_id':key1.split('_')[1], 'answer' : val1})
740 sur_name_read['store_ans'][resp_id].update({key1:val1})
743 for res in resp_id_list:
744 sur_name_read['store_ans'].pop(res)
745 raise osv.except_osv(_('Warning !'), "'" + que_rec['question'] + "' \n" + _("Please enter an integer value"))
747 elif val1 and que_id == key1.split('_')[0] and len(key1.split('_')) == 3:
748 if type(val1) == type('') or type(val1) == type(u''):
749 ans_create_id = res_ans_obj.create(cr, uid, {'response_id':resp_id, 'answer_id':key1.split('_')[1], 'column_id' : key1.split('_')[2], 'value_choice' : val1})
750 sur_name_read['store_ans'][resp_id].update({key1:val1})
752 ans_create_id = res_ans_obj.create(cr, uid, {'response_id':resp_id, 'answer_id':key1.split('_')[1], 'column_id' : key1.split('_')[2]})
753 sur_name_read['store_ans'][resp_id].update({key1:True})
755 matrix_list.append(key1.split('_')[0] + '_' + key1.split('_')[1])
758 elif val1 and que_id == key1.split('_')[0] and len(key1.split('_')) == 2:
759 ans_create_id = res_ans_obj.create(cr, uid, {'response_id':resp_id, 'answer_id':key1.split('_')[-1], 'answer' : val1})
760 sur_name_read['store_ans'][resp_id].update({key1:val1})
762 surv_name_wiz.write(cr, uid, [context.get('sur_name_id',False)], {'store_ans':sur_name_read['store_ans']})
764 for key,val in vals.items():
765 if val and key.split('_')[1] == "commentcolumn" and key.split('_')[0] == que_id:
766 for res_id in response_list:
767 if key.split('_')[2] in res_id.split('_')[1]:
768 a = res_ans_obj.write(cr, uid, [res_id.split('_')[0]], {'comment_field':val})
769 sur_name_read['store_ans'][resp_id].update({key:val})
771 if comment_field and comment_value:
772 for res in resp_id_list:
773 sur_name_read['store_ans'].pop(res)
774 raise osv.except_osv(_('Warning !'), "'" + que_rec['question'] + "' " + tools.ustr(que_rec['make_comment_field_err_msg']))
776 if que_rec['type'] == "rating_scale" and que_rec['rating_allow_one_column_require'] and len(selected_value) > len(list(set(selected_value))):
777 for res in resp_id_list:
778 sur_name_read['store_ans'].pop(res)
779 raise osv.except_osv(_('Warning !'), "'" + que_rec['question'] + "'\n" + _("You cannot select the same answer more than one time"))
782 resp_obj.write(cr, uid, resp_id, {'state':'skip'})
784 if que_rec['numeric_required_sum'] and numeric_sum > que_rec['numeric_required_sum']:
785 for res in resp_id_list:
786 sur_name_read['store_ans'].pop(res)
787 raise osv.except_osv(_('Warning !'), "'" + que_rec['question'] + "' " + tools.ustr(que_rec['numeric_required_sum_err_msg']))
789 if que_rec['type'] in ['multiple_textboxes_diff_type', 'multiple_choice_multiple_ans','matrix_of_choices_only_one_ans','matrix_of_choices_only_multi_ans','matrix_of_drop_down_menus','rating_scale','multiple_textboxes','numerical_textboxes','date','date_and_time'] and que_rec['is_require_answer']:
791 if (que_rec['required_type'] == 'all' and len(list(set(matrix_list))) < len(que_rec['answer_choice_ids'])) or \
792 (que_rec['required_type'] == 'at least' and len(list(set(matrix_list))) < que_rec['req_ans']) or \
793 (que_rec['required_type'] == 'at most' and len(list(set(matrix_list))) > que_rec['req_ans']) or \
794 (que_rec['required_type'] == 'exactly' and len(list(set(matrix_list))) != que_rec['req_ans']) or \
795 (que_rec['required_type'] == 'a range' and (len(list(set(matrix_list))) < que_rec['minimum_req_ans'] or len(list(set(matrix_list))) > que_rec['maximum_req_ans'])):
796 for res in resp_id_list:
797 sur_name_read['store_ans'].pop(res)
798 raise osv.except_osv(_('Warning !'), "'" + que_rec['question'] + "' " + tools.ustr(que_rec['req_error_msg']))
800 elif (que_rec['required_type'] == 'all' and select_count < len(que_rec['answer_choice_ids'])) or \
801 (que_rec['required_type'] == 'at least' and select_count < que_rec['req_ans']) or \
802 (que_rec['required_type'] == 'at most' and select_count > que_rec['req_ans']) or \
803 (que_rec['required_type'] == 'exactly' and select_count != que_rec['req_ans']) or \
804 (que_rec['required_type'] == 'a range' and (select_count < que_rec['minimum_req_ans'] or select_count > que_rec['maximum_req_ans'])):
805 for res in resp_id_list:
806 sur_name_read['store_ans'].pop(res)
807 raise osv.except_osv(_('Warning !'), "'" + que_rec['question'] + "' " + tools.ustr(que_rec['req_error_msg']))
809 if que_rec['type'] in ['multiple_choice_only_one_ans','single_textbox','comment'] and que_rec['is_require_answer'] and select_count <= 0:
810 for res in resp_id_list:
811 sur_name_read['store_ans'].pop(res)
812 raise osv.except_osv(_('Warning !'), "'" + que_rec['question'] + "' " + tools.ustr(que_rec['req_error_msg']))
816 for update in click_update:
817 que_rec = que_obj.read(cr, uid , [int(sur_name_read['store_ans'][update]['question_id'])], [])[0]
818 res_ans_obj.unlink(cr, uid,res_ans_obj.search(cr, uid, [('response_id', '=', update)]))
819 surv_tbl_column_obj.unlink(cr, uid,surv_tbl_column_obj.search(cr, uid, [('response_table_id', '=', update)]))
820 resp_id_list.append(update)
821 sur_name_read['store_ans'].update({update:{'question_id':sur_name_read['store_ans'][update]['question_id']}})
822 surv_name_wiz.write(cr, uid, [context.get('sur_name_id',False)], {'store_ans':sur_name_read['store_ans']})
827 comment_field = False
828 comment_value = False
831 for key, val in vals.items():
832 ans_id_len = key.split('_')
833 if ans_id_len[0] == sur_name_read['store_ans'][update]['question_id']:
834 if val and key.split('_')[1] == "table":
835 surv_tbl_column_obj.create(cr, uid, {'response_table_id' : update,'column_id':key.split('_')[2], 'name':key.split('_')[3], 'value' : val})
836 sur_name_read['store_ans'][update].update({key:val})
837 resp_obj.write(cr, uid, update, {'state': 'done'})
839 elif val and key.split('_')[1] == "otherfield" :
841 sur_name_read['store_ans'][update].update({key:val})
843 surv_name_wiz.write(cr, uid, [context.get('sur_name_id',False)], {'store_ans':sur_name_read['store_ans']})
846 elif val and key.split('_')[1] == "selection":
847 if len(key.split('_')) > 2:
848 ans_create_id = res_ans_obj.create(cr, uid, {'response_id':update, 'answer_id':key.split('_')[-1], 'column_id' : val})
849 selected_value.append(val)
850 response_list.append(str(ans_create_id) + "_" + str(key.split('_')[-1]))
852 ans_create_id = res_ans_obj.create(cr, uid, {'response_id':update, 'answer_id': val})
853 resp_obj.write(cr, uid, update, {'state': 'done'})
854 sur_name_read['store_ans'][update].update({key:val})
857 elif key.split('_')[1] == "other":
862 if que_rec['is_comment_require'] and que_rec['comment_valid_type'] == 'must_be_specific_length':
863 if (not val and que_rec['comment_minimum_no']) or len(val) < que_rec['comment_minimum_no'] or len(val) > que_rec['comment_maximum_no']:
865 elif que_rec['is_comment_require'] and que_rec['comment_valid_type'] in ['must_be_whole_number', 'must_be_decimal_number', 'must_be_date']:
867 if que_rec['comment_valid_type'] == 'must_be_whole_number':
869 if value < que_rec['comment_minimum_no'] or value > que_rec['comment_maximum_no']:
871 elif que_rec['comment_valid_type'] == 'must_be_decimal_number':
873 if value < que_rec['comment_minimum_float'] or value > que_rec['comment_maximum_float']:
875 elif que_rec['comment_valid_type'] == 'must_be_date':
876 value = datetime.datetime.strptime(val, "%Y-%m-%d")
877 if value < datetime.datetime.strptime(que_rec['comment_minimum_date'], "%Y-%m-%d") or value > datetime.datetime.strptime(que_rec['comment_maximum_date'], "%Y-%m-%d"):
881 elif que_rec['is_comment_require'] and que_rec['comment_valid_type'] == 'must_be_email_address':
883 if re.match("^[a-zA-Z0-9._%-+]+@[a-zA-Z0-9._%-]+.[a-zA-Z]{2,6}$", val) == None:
886 raise osv.except_osv(_('Warning !'), "'" + que_rec['question'] + "' \n" + tools.ustr(que_rec['comment_valid_err_msg']))
887 resp_obj.write(cr, uid, update, {'comment':val,'state': 'done'})
888 sur_name_read['store_ans'][update].update({key:val})
890 elif val and key.split('_')[1] == "comment":
891 resp_obj.write(cr, uid, update, {'comment':val,'state': 'done'})
892 sur_name_read['store_ans'][update].update({key:val})
895 elif val and (key.split('_')[1] == "single" or (len(key.split('_')) > 2 and key.split('_')[2] == 'multi')):
897 if que_rec['is_validation_require'] and que_rec['validation_type'] == 'must_be_specific_length':
898 if (not val and que_rec['validation_minimum_no']) or len(val) < que_rec['validation_minimum_no'] or len(val) > que_rec['validation_maximum_no']:
900 elif que_rec['is_validation_require'] and que_rec['validation_type'] in ['must_be_whole_number', 'must_be_decimal_number', 'must_be_date']:
903 if que_rec['validation_type'] == 'must_be_whole_number':
905 if value < que_rec['validation_minimum_no'] or value > que_rec['validation_maximum_no']:
907 elif que_rec['validation_type'] == 'must_be_decimal_number':
909 if value < que_rec['validation_minimum_float'] or value > que_rec['validation_maximum_float']:
911 elif que_rec['validation_type'] == 'must_be_date':
912 value = datetime.datetime.strptime(val, "%Y-%m-%d")
913 if value < datetime.datetime.strptime(que_rec['validation_minimum_date'], "%Y-%m-%d") or value > datetime.datetime.strptime(que_rec['validation_maximum_date'], "%Y-%m-%d"):
917 elif que_rec['is_validation_require'] and que_rec['validation_type'] == 'must_be_email_address':
919 if re.match("^[a-zA-Z0-9._%-+]+@[a-zA-Z0-9._%-]+.[a-zA-Z]{2,6}$", val) == None:
922 raise osv.except_osv(_('Warning !'), "'" + que_rec['question'] + "' \n" + tools.ustr(que_rec['validation_valid_err_msg']))
923 if key.split('_')[1] == "single" :
924 resp_obj.write(cr, uid, update, {'single_text':val,'state': 'done'})
926 resp_obj.write(cr, uid, update, {'state': 'done'})
927 ans_create_id = res_ans_obj.create(cr, uid, {'response_id':update, 'answer_id':ans_id_len[1], 'answer' : val})
928 sur_name_read['store_ans'][update].update({key:val})
931 elif val and len(key.split('_')) > 2 and key.split('_')[2] == 'numeric':
934 numeric_sum += int(val)
935 resp_obj.write(cr, uid, update, {'state': 'done'})
936 ans_create_id = res_ans_obj.create(cr, uid, {'response_id': update, 'answer_id':ans_id_len[1], 'answer' : val})
937 sur_name_read['store_ans'][update].update({key:val})
940 raise osv.except_osv(_('Warning !'), "'" + que_rec['question'] + "'\n" + _("Please enter an integer value"))
942 elif val and len(key.split('_')) == 3:
943 resp_obj.write(cr, uid, update, {'state': 'done'})
944 if type(val) == type('') or type(val) == type(u''):
945 ans_create_id = res_ans_obj.create(cr, uid, {'response_id': update, 'answer_id':ans_id_len[1], 'column_id' : ans_id_len[2], 'value_choice' : val})
946 sur_name_read['store_ans'][update].update({key:val})
948 ans_create_id = res_ans_obj.create(cr, uid, {'response_id': update, 'answer_id':ans_id_len[1], 'column_id' : ans_id_len[2]})
949 sur_name_read['store_ans'][update].update({key:True})
950 matrix_list.append(key.split('_')[0] + '_' + key.split('_')[1])
953 elif val and len(key.split('_')) == 2:
954 resp_obj.write(cr, uid, update, {'state': 'done'})
955 ans_create_id = res_ans_obj.create(cr, uid, {'response_id': update, 'answer_id':ans_id_len[-1], 'answer' : val})
956 sur_name_read['store_ans'][update].update({key:val})
958 surv_name_wiz.write(cr, uid, [context.get('sur_name_id',False)], {'store_ans': sur_name_read['store_ans']})
960 for key,val in vals.items():
961 if val and key.split('_')[1] == "commentcolumn" and key.split('_')[0] == sur_name_read['store_ans'][update]['question_id']:
962 for res_id in response_list:
963 if key.split('_')[2] in res_id.split('_')[1]:
964 a = res_ans_obj.write(cr, uid, [res_id.split('_')[0]], {'comment_field':val})
965 sur_name_read['store_ans'][update].update({key:val})
967 if comment_field and comment_value:
968 raise osv.except_osv(_('Warning !'), "'" + que_rec['question'] + "' " + tools.ustr(que_rec['make_comment_field_err_msg']))
970 if que_rec['type'] == "rating_scale" and que_rec['rating_allow_one_column_require'] and len(selected_value) > len(list(set(selected_value))):
971 raise osv.except_osv(_('Warning !'), "'" + que_rec['question'] + "\n" + _("You cannot select same answer more than one time'"))
973 if que_rec['numeric_required_sum'] and numeric_sum > que_rec['numeric_required_sum']:
974 raise osv.except_osv(_('Warning !'), "'" + que_rec['question'] + "' " + tools.ustr(que_rec['numeric_required_sum_err_msg']))
977 resp_obj.write(cr, uid, update, {'state': 'skip'})
979 if que_rec['type'] in ['multiple_textboxes_diff_type','multiple_choice_multiple_ans','matrix_of_choices_only_one_ans','matrix_of_choices_only_multi_ans','matrix_of_drop_down_menus','rating_scale','multiple_textboxes','numerical_textboxes','date','date_and_time'] and que_rec['is_require_answer']:
981 if (que_rec['required_type'] == 'all' and len(list(set(matrix_list))) < len(que_rec['answer_choice_ids'])) or \
982 (que_rec['required_type'] == 'at least' and len(list(set(matrix_list))) < que_rec['req_ans']) or \
983 (que_rec['required_type'] == 'at most' and len(list(set(matrix_list))) > que_rec['req_ans']) or \
984 (que_rec['required_type'] == 'exactly' and len(list(set(matrix_list))) != que_rec['req_ans']) or \
985 (que_rec['required_type'] == 'a range' and (len(list(set(matrix_list))) < que_rec['minimum_req_ans'] or len(list(set(matrix_list))) > que_rec['maximum_req_ans'])):
986 raise osv.except_osv(_('Warning !'), "'" + que_rec['question'] + "' " + tools.ustr(que_rec['req_error_msg']))
988 elif (que_rec['required_type'] == 'all' and select_count < len(que_rec['answer_choice_ids'])) or \
989 (que_rec['required_type'] == 'at least' and select_count < que_rec['req_ans']) or \
990 (que_rec['required_type'] == 'at most' and select_count > que_rec['req_ans']) or \
991 (que_rec['required_type'] == 'exactly' and select_count != que_rec['req_ans']) or \
992 (que_rec['required_type'] == 'a range' and (select_count < que_rec['minimum_req_ans'] or select_count > que_rec['maximum_req_ans'])):
993 raise osv.except_osv(_('Warning !'), "'" + que_rec['question'] + "' " + tools.ustr(que_rec['req_error_msg']))
995 if que_rec['type'] in ['multiple_choice_only_one_ans','single_textbox','comment'] and que_rec['is_require_answer'] and select_count <= 0:
996 raise osv.except_osv(_('Warning !'), "'" + que_rec['question'] + "' " + tools.ustr(que_rec['req_error_msg']))
998 return survey_question_wiz_id
1000 def action_new_question(self,cr, uid, ids, context=None):
1002 New survey.Question form.
1006 for key,val in context.items():
1007 if type(key) == type(True):
1009 view_id = self.pool.get('ir.ui.view').search(cr,uid,[('model','=','survey.question'),\
1010 ('name','=','survey_question_wizard_test')])
1012 'view_type': 'form',
1013 "view_mode": 'form',
1014 'res_model': 'survey.question',
1015 'type': 'ir.actions.act_window',
1021 def action_new_page(self, cr, uid, ids, context=None):
1023 New survey.Page form.
1027 for key,val in context.items():
1028 if type(key) == type(True):
1030 view_id = self.pool.get('ir.ui.view').search(cr,uid,[('model','=','survey.page'),\
1031 ('name','=','survey_page_wizard_test')])
1033 'view_type': 'form',
1034 "view_mode": 'form',
1035 'res_model': 'survey.page',
1036 'type': 'ir.actions.act_window',
1042 def action_edit_page(self,cr, uid, ids, context=None):
1048 for key,val in context.items():
1049 if type(key) == type(True):
1051 view_id = self.pool.get('ir.ui.view').search(cr,uid,[('model','=','survey.page'),\
1052 ('name','=','survey_page_wizard_test')])
1054 'view_type': 'form',
1055 "view_mode": 'form',
1056 'res_model': 'survey.page',
1057 'type': 'ir.actions.act_window',
1059 'res_id': int(context.get('page_id',0)),
1064 def action_delete_page(self,cr, uid, ids, context=None):
1070 for key,val in context.items():
1071 if type(key) == type(True):
1074 self.pool.get('survey.page').unlink(cr, uid, [context.get('page_id',False)])
1075 search_id = self.pool.get('ir.ui.view').search(cr,uid,[('model','=','survey.question.wiz'),\
1076 ('name','=','Survey Search')])
1077 surv_name_wiz = self.pool.get('survey.name.wiz')
1078 surv_name_wiz.write(cr, uid, [context.get('sur_name_id',False)], \
1079 {'transfer':True, 'page_no' : context.get('page_number',False) })
1081 'view_type': 'form',
1082 "view_mode": 'form',
1083 'res_model': 'survey.question.wiz',
1084 'type': 'ir.actions.act_window',
1086 'search_view_id':search_id[0],
1090 def action_edit_question(self,cr, uid, ids, context=None):
1092 Edit survey.question.
1096 for key,val in context.items():
1097 if type(key) == type(True):
1099 view_id = self.pool.get('ir.ui.view').search(cr,uid,[('model','=','survey.question'),\
1100 ('name','=','survey_question_wizard_test')])
1102 'view_type': 'form',
1103 "view_mode": 'form',
1104 'res_model': 'survey.question',
1105 'type': 'ir.actions.act_window',
1107 'res_id' : int(context.get('question_id',0)),
1112 def action_delete_question(self,cr, uid, ids, context=None):
1114 Delete survey.question.
1118 for key,val in context.items():
1119 if type(key) == type(True):
1122 que_obj = self.pool.get('survey.question')
1123 que_obj.unlink(cr, uid, [context.get('question_id',False)])
1124 search_id = self.pool.get('ir.ui.view').search(cr,uid,[('model','=','survey.question.wiz'),\
1125 ('name','=','Survey Search')])
1126 surv_name_wiz = self.pool.get('survey.name.wiz')
1127 surv_name_wiz.write(cr, uid, [context.get('sur_name_id',False)],\
1128 {'transfer':True, 'page_no' : context.get('page_number',0) })
1130 'view_type': 'form',
1131 "view_mode": 'form',
1132 'res_model': 'survey.question.wiz',
1133 'type': 'ir.actions.act_window',
1135 'search_view_id': search_id[0],
1139 def action_forward_previous(self, cr, uid, ids, context=None):
1141 Goes to previous Survey Answer.
1145 search_obj = self.pool.get('ir.ui.view')
1146 surv_name_wiz = self.pool.get('survey.name.wiz')
1147 search_id = search_obj.search(cr,uid,[('model','=','survey.question.wiz'),\
1148 ('name','=','Survey Search')])
1149 wiz_id = surv_name_wiz.create(cr,uid, {'survey_id': context.get('survey_id',False),'page_no' :-1,'page':'next','transfer' :1,'response':0})
1150 context.update({'sur_name_id' :wiz_id, 'response_no': context.get('response_no',0) - 1})
1152 if context.get('response_no',0) + 1 > len(context.get('response_id',0)):
1155 'view_type': 'form',
1156 "view_mode": 'form',
1157 'res_model': 'survey.question.wiz',
1158 'type': 'ir.actions.act_window',
1160 'search_view_id': search_id[0],
1164 def action_forward_next(self, cr, uid, ids, context=None):
1166 Goes to Next Survey Answer.
1170 search_obj = self.pool.get('ir.ui.view')
1171 surv_name_wiz = self.pool.get('survey.name.wiz')
1172 search_id = search_obj.search(cr,uid,[('model','=','survey.question.wiz'),\
1173 ('name','=','Survey Search')])
1174 wiz_id = surv_name_wiz.create(cr,uid, {'survey_id' : context.get('survey_id',False),'page_no' :-1,'page':'next','transfer' :1,'response':0})
1175 context.update({'sur_name_id' :wiz_id, 'response_no' : context.get('response_no',0) + 1})
1177 if context.get('response_no',0) + 1 > len(context.get('response_id',0)):
1180 'view_type': 'form',
1181 "view_mode": 'form',
1182 'res_model': 'survey.question.wiz',
1183 'type': 'ir.actions.act_window',
1185 'search_view_id': search_id[0],
1189 def action_next(self, cr, uid, ids, context=None):
1195 surv_name_wiz = self.pool.get('survey.name.wiz')
1196 search_obj = self.pool.get('ir.ui.view')
1197 search_id = search_obj.search(cr,uid,[('model','=','survey.question.wiz'),('name','=','Survey Search')])
1198 surv_name_wiz.write(cr, uid, [context.get('sur_name_id',False)], {'transfer':True, 'page':'next'})
1200 'view_type': 'form',
1201 "view_mode": 'form',
1202 'res_model': 'survey.question.wiz',
1203 'type': 'ir.actions.act_window',
1205 'search_view_id': search_id[0],
1209 def action_previous(self, cr, uid, ids, context=None):
1211 Goes to previous page.
1215 surv_name_wiz = self.pool.get('survey.name.wiz')
1216 search_obj = self.pool.get('ir.ui.view')
1217 search_id = search_obj.search(cr,uid,[('model','=','survey.question.wiz'),\
1218 ('name','=','Survey Search')])
1219 surv_name_wiz.write(cr, uid, [context.get('sur_name_id',False)], {'transfer':True, 'page':'previous'})
1221 'view_type': 'form',
1222 "view_mode": 'form',
1223 'res_model': 'survey.question.wiz',
1224 'type': 'ir.actions.act_window',
1226 'search_view_id': search_id[0],
1230 survey_question_wiz()
1232 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: