[IMP] sale order line invisible type
[odoo/odoo.git] / addons / survey / wizard / survey_answer.py
1 ## -*- coding: utf-8 -*-
2 ##############################################################################
3 #
4 #    OpenERP, Open Source Management Solution
5 #    Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
6 #
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.
11 #
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.
16 #
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/>.
19 #
20 ##############################################################################
21 import os
22 import datetime
23 from lxml import etree
24 from time import strftime
25
26 import base64
27 import tools
28 import netsvc
29 from osv import osv
30 from osv import fields
31 from tools import to_xml
32 from tools.translate import _
33 import addons
34 from tools.safe_eval import safe_eval
35
36 class survey_question_wiz(osv.osv_memory):
37     _name = 'survey.question.wiz'
38     _columns = {
39         'name': fields.integer('Number'),
40     }
41
42     def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
43         """
44         Fields View Get method :- generate the new view and display the survey pages of selected survey.
45         """
46         if context is None:
47             context = {}
48         result = super(survey_question_wiz, self).fields_view_get(cr, uid, view_id, \
49                                         view_type, context, toolbar,submenu)
50
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')
60         
61         if view_type in ['form']:
62             wiz_id = 0
63             sur_name_rec = None
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:
67                 res_data = {
68                     'survey_id': context.get('survey_id', False),
69                     'page_no': -1,
70                     'page': 'next',
71                     'transfer': 1,
72                     'response': 0
73                 }
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})
77
78             if context.has_key('active_id'):
79                 context.pop('active_id')
80
81             survey_id = context.get('survey_id', False)
82             if not survey_id:
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
86                 else:
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)
98             pre_button = False
99             readonly = 0
100
101             if context.get('response_id', False) \
102                             and int(context['response_id'][0]) > 0:
103                 readonly = 1
104
105             if not sur_name_rec.page_no + 1 :
106                 surv_name_wiz.write(cr, uid, [context['sur_name_id'],], {'store_ans':{}})
107
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})
112                 flag = False
113                 fields = {}
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 cannot 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 cannot answer this survey more than %s times.") % (user_limit))
127
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")})
130
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})
133                         flag = True
134                         page_number += 1
135                     if sur_name_rec.page_no > - 1:
136                         pre_button = True
137                 else:
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})
142                         flag = True
143                         page_number -= 1
144
145                     if sur_name_rec.page_no > 1:
146                         pre_button = True
147                 if flag:
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)})
162
163                     if wiz_id:
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)})
166
167                     if pag_rec.note:
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
172                     qu_no = 0
173
174                     for que in que_ids:
175                         qu_no += 1
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:
180                             star = '*'
181                         else:
182                             star = ''
183                         xml_group = etree.SubElement(xml_form, 'group', {'col': '2', 'colspan': '4'})
184
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)})
193                         else:
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'})
196
197                         ans_ids = que_rec.answer_choice_ids
198                         xml_group = etree.SubElement(xml_form, 'group', {'col': '1', 'colspan': '4'})
199
200                         if que_rec.type == 'multiple_choice_only_one_ans':
201                             selection = []
202                             for ans in ans_ids:
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"}
207
208                         elif que_rec.type == 'multiple_choice_multiple_ans':
209                             xml_group = etree.SubElement(xml_group, 'group', {'col': '4', 'colspan': '4'})
210                             for ans in ans_ids:
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}
213
214                         elif que_rec.type in ['matrix_of_choices_only_one_ans', 'rating_scale']:
215                             if que_rec.comment_column:
216                                 col = "4"
217                                 colspan = "4"
218                             else:
219                                col = "2"
220                                colspan = "2"
221                             xml_group = etree.SubElement(xml_group, 'group', {'col': tools.ustr(col), 'colspan': tools.ustr(colspan)})
222                             for row in ans_ids:
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"})
232
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'})
238                             for row in ans_ids:
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}
243
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'})
249                             for row in ans_ids:
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:
252                                     selection = []
253                                     if col.menu_choice:
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}
258
259                         elif que_rec.type == 'multiple_textboxes':
260                             xml_group = etree.SubElement(xml_group, 'group', {'col': '4', 'colspan': '4'})
261                             type = "char"
262                             if que_rec.is_validation_require:
263                                 if que_rec.validation_type in ['must_be_whole_number']:
264                                     type = "integer"
265                                 elif que_rec.validation_type in ['must_be_decimal_number']:
266                                     type = "float"
267                                 elif que_rec.validation_type in ['must_be_date']:
268                                     type = "date"
269                             for ans in ans_ids:
270                                 etree.SubElement(xml_group, 'field', {'readonly': str(readonly), 'width':"300",'colspan': '1','name': tools.ustr(que.id) + "_" + tools.ustr(ans.id) + "_multi"})
271                                 if type == "char" :
272                                     fields[tools.ustr(que.id) + "_" + tools.ustr(ans.id) + "_multi"] = {'type':'char', 'size':255, 'string':ans.answer}
273                                 else:
274                                     fields[tools.ustr(que.id) + "_" + tools.ustr(ans.id) + "_multi"] = {'type': str(type), 'string':ans.answer}
275
276                         elif que_rec.type == 'numerical_textboxes':
277                             xml_group = etree.SubElement(xml_group, 'group', {'col': '4', 'colspan': '4'})
278                             for ans in ans_ids:
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}
281
282                         elif que_rec.type == 'date':
283                             xml_group = etree.SubElement(xml_group, 'group', {'col': '4', 'colspan': '4'})
284                             for ans in ans_ids:
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}
287
288                         elif que_rec.type == 'date_and_time':
289                             xml_group = etree.SubElement(xml_group, 'group', {'col': '4', 'colspan': '4'})
290                             for ans in ans_ids:
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}
293
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"})
298
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':{}}
302
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':{}}
306
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':{}}
315
316                         elif que_rec.type == 'multiple_textboxes_diff_type':
317                             xml_group = etree.SubElement(xml_group, 'group', {'col': '4', 'colspan': '4'})
318                             for ans in ans_ids:
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"})
322                                 else:
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}
328                                     else:
329                                         selection = []
330                                         if ans.menu_choice:
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}
334
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':{}}
345                             else:
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':{}}
354
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"})
361                     
362                     if pre_button:
363                         etree.SubElement(xml_group, 'button', {'colspan':"1",'icon':"gtk-go-back",'name':"action_previous",'string':"Previous",'type':"object"})
364                     but_string = "Next"
365                     if int(page_number) + 1 == total_pages:
366                         but_string = "Done"
367
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)})
374                     else:
375                         etree.SubElement(xml_group, 'button', {'icon': "gtk-go-forward", 'name':"action_next",'string': tools.ustr(but_string) ,'type':"object",'context' : tools.ustr(context)})
376
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)})
385
386                     root = xml_form.getroottree()
387                     result['arch'] = etree.tostring(root)
388                     result['fields'] = fields
389                     result['context'] = context
390                 else:
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'})
393
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)
398
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)
404                         attachments = {}
405                         file = open(addons.get_module_resource('survey', 'report') + survey_data.title + ".pdf")
406                         file_data = ""
407                         while 1:
408                             line = file.readline()
409                             file_data += line
410                             if not line:
411                                 break
412
413                         attachments[survey_data.title + ".pdf"] = file_data
414                         file.close()
415                         os.remove(addons.get_module_resource('survey', 'report') + survey_data.title + ".pdf")
416                         
417                         user_email = user_obj.browse(cr, uid, uid, context).email
418                         resp_email = survey_data.responsible_id and survey_data.responsible_id.email or False
419
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)
424
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
434         return result
435
436     def create_report(self, cr, uid, res_ids, report_name=False, file_name=False, context=None):
437         """
438         If any user give answer of survey then last create report of this answer and if 'Email Notification on Answer' set True in survey  then send mail on responsible person of this survey and attach survey answer report in pdf format.
439         """
440         if not report_name or not res_ids:
441             return (False, Exception('Report name and Resources ids are required !!!'))
442         try:
443             uid = 1
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+');
448             fp.write(result);
449             fp.close();
450             
451             # hr.applicant: if survey answered directly in system: attach report to applicant
452             if context.get('active_model') == 'hr.applicant':
453                 self.pool.get('hr.applicant').write(cr,uid,[context.get('active_ids')[0]],{'response':context.get('response_id')})
454                 result = base64.b64encode(result)
455                 file_name = file_name + '.pdf'
456                 ir_attachment = self.pool.get('ir.attachment').create(cr, uid, 
457                                                                       {'name': file_name,
458                                                                        'datas': result,
459                                                                        'datas_fname': file_name,
460                                                                        'res_model': context.get('active_model'),
461                                                                        'res_id': context.get('active_ids')[0]},
462                                                                       context=context)
463
464         except Exception,e:
465             return (False, str(e))
466
467         return (True, ret_file_name)
468
469     def default_get(self, cr, uid, fields_list, context=None):
470         """
471         Assign Default value in particular field. If Browse Answers wizard run then read the value into database and Assigne to a particular fields.
472         """
473         value = {}
474         if context is None:
475             context = {}
476         for field in fields_list:
477             if field.split('_')[0] == 'progress':
478                 tot_page_id = self.pool.get('survey').browse(cr, uid, context.get('survey_id',False))
479                 tot_per = (float(100) * (int(field.split('_')[2]) + 1) / len(tot_page_id.page_ids))
480                 value[field] = tot_per
481         response_obj = self.pool.get('survey.response')
482         surv_name_wiz = self.pool.get('survey.name.wiz')
483
484         if context.has_key('response_id') and context.get('response_id') and int(context['response_id'][0]) > 0:
485             data = super(survey_question_wiz, self).default_get(cr, uid, fields_list, context)
486             response_ans = response_obj.browse(cr, uid, context['response_id'][context['response_no']])
487             fields_list.sort()
488
489             for que in response_ans.question_ids:
490                 for field in fields_list:
491                     if field.split('_')[0] != "progress" and field.split('_')[0] == str(que.question_id.id):
492                         if que.response_answer_ids and len(field.split('_')) == 4 and field.split('_')[1] == "commentcolumn" and field.split('_')[3] == "field":
493                             for ans in que.response_answer_ids:
494                                 if str(field.split('_')[2]) == str(ans.answer_id.id):
495                                     value[field] = ans.comment_field
496
497                         if que.response_table_ids and len(field.split('_')) == 4 and field.split('_')[1] == "table":
498                             for ans in que.response_table_ids:
499                                 if str(field.split('_')[2]) == str(ans.column_id.id) and str(field.split('_')[3]) ==  str(ans.name):
500                                     value[field] = ans.value
501
502                         if que.comment and (field.split('_')[1] == "comment" or field.split('_')[1] == "other"):
503                             value[field] = str(que.comment)
504
505                         elif que.single_text and field.split('_')[1] == "single":
506                             value[field] = str(que.single_text)
507
508                         elif que.response_answer_ids and len(field.split('_')) == 3 and field.split('_')[1] == "selection":
509                             for ans in que.response_answer_ids:
510                                 if str(field.split('_')[2]) == str( ans.answer_id.id):
511                                     value[field] = str(ans.column_id.id)
512
513                         elif que.response_answer_ids and len(field.split('_')) == 2 and field.split('_')[1] == "selection":
514                             value[field] = str(que.response_answer_ids[0].answer_id.id)
515
516                         elif que.response_answer_ids and len(field.split('_')) == 3 and field.split('_')[2] != "multi" and field.split('_')[2] != "numeric":
517                             for ans in que.response_answer_ids:
518                                 if str(field.split('_')[1]) == str( ans.answer_id.id) and str(field.split('_')[2]) == str(ans.column_id.id):
519                                     if ans.value_choice:
520                                         value[field] = ans.value_choice
521                                     else:
522                                         value[field] = True
523
524                         else:
525                             for ans in que.response_answer_ids:
526                                 if str(field.split('_')[1]) == str( ans.answer_id.id):
527                                     value[field] = ans.answer
528
529         else:
530             if not context.has_key('sur_name_id'):
531                 return value
532             if context.has_key('active') and context.get('active',False):
533                 return value
534             
535             sur_name_read = surv_name_wiz.read(cr, uid, context.get('sur_name_id',False))
536             ans_list = []
537
538             for key,val in safe_eval(sur_name_read.get('store_ans',"{}")).items():
539                 for field in fields_list:
540                     if field in list(val):
541                         value[field] = val[field]
542
543         return value
544
545     def create(self, cr, uid, vals, context=None):
546         """
547         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         """
549         if context is None: context = {}
550
551         survey_question_wiz_id = super(survey_question_wiz,self).create(cr, uid, {'name': vals.get('name')}, context=context)
552         if context.has_key('active') and context.get('active',False):
553             return survey_question_wiz_id
554
555         for key,val in vals.items():
556             if key.split('_')[0] == "progress":
557                 vals.pop(key)
558             if not context.has_key('sur_name_id') and key.split('_')[0] == "wizardid":
559                 context.update({'sur_name_id': int(key.split('_')[1])})
560                 vals.pop(key)
561
562         click_state = True
563         click_update = []
564         surv_name_wiz = self.pool.get('survey.name.wiz')
565         surv_all_resp_obj = self.pool.get('survey.response')
566         surv_tbl_column_obj = self.pool.get('survey.tbl.column.heading')
567         survey_obj = self.pool.get('survey')
568         resp_obj = self.pool.get('survey.response.line')
569         res_ans_obj = self.pool.get('survey.response.answer')
570         que_obj = self.pool.get('survey.question')
571         sur_name_read = surv_name_wiz.read(cr, uid, context.get('sur_name_id',False), [])
572         response_id =  0
573
574         if not sur_name_read['response']:
575             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']})
576             surv_name_wiz.write(cr, uid, [context.get('sur_name_id', False)], {'response' : tools.ustr(response_id)})
577         else:
578             response_id = int(sur_name_read['response'])
579
580         if response_id not in surv_all_resp_obj.search(cr, uid, []):
581             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)})
582             surv_name_wiz.write(cr, uid, [context.get('sur_name_id',False)], {'response' : tools.ustr(response_id)})
583
584         #click first time on next button then increemnet on total start suvey
585         if not safe_eval(sur_name_read['store_ans']):
586             his_id = self.pool.get('survey.history').create(cr, uid, {'user_id': uid, \
587                                               'date': strftime('%Y-%m-%d %H:%M:%S'), 'survey_id': sur_name_read['survey_id'][0]})
588             survey_id = sur_name_read['survey_id'][0]
589             sur_rec = survey_obj.read(cr, uid, survey_id)
590             survey_obj.write(cr, uid, survey_id,  {'tot_start_survey' : sur_rec['tot_start_survey'] + 1})
591             if context.has_key('cur_id'):
592                 if context.has_key('request') and context.get('request',False):
593                     self.pool.get(context.get('object',False)).write(cr, uid, [int(context.get('cur_id',False))], {'response' : response_id})
594                     self.pool.get(context.get('object',False)).survey_req_done(cr, uid, [int(context.get('cur_id'))], context)
595                 else:
596                     self.pool.get(context.get('object',False)).write(cr, uid, [int(context.get('cur_id',False))], {'response' : response_id})
597         if sur_name_read['store_ans'] and type(sur_name_read['store_ans']) == dict:
598             for key,val in sur_name_read['store_ans'].items():
599                 for field in vals:
600                     if field.split('_')[0] == val['question_id']:
601                         click_state = False
602                         click_update.append(key)
603                         break
604         else:
605             sur_name_read['store_ans'] = {}
606         if click_state:
607             que_li = []
608             resp_id_list = []
609             for key, val in vals.items():
610                 que_id = key.split('_')[0]
611                 if que_id not in que_li:
612                     que_li.append(que_id)
613                     que_rec = que_obj.read(cr, uid, [int(que_id)], [])[0]
614                     res_data =  {
615                         'question_id': que_id,
616                         'date_create': datetime.datetime.now(),
617                         'state': 'done',
618                         'response_id': response_id
619                     }
620                     resp_id = resp_obj.create(cr, uid, res_data)
621                     resp_id_list.append(resp_id)
622                     sur_name_read['store_ans'].update({resp_id:{'question_id':que_id}})
623                     surv_name_wiz.write(cr, uid, [context.get('sur_name_id',False)], {'store_ans':sur_name_read['store_ans']})
624                     select_count = 0
625                     numeric_sum = 0
626                     selected_value = []
627                     matrix_list = []
628                     comment_field = False
629                     comment_value = False
630                     response_list = []
631
632                     for key1, val1 in vals.items():
633                         if val1 and key1.split('_')[1] == "table" and key1.split('_')[0] == que_id:
634                             surv_tbl_column_obj.create(cr, uid, {'response_table_id' : resp_id,'column_id':key1.split('_')[2], 'name':key1.split('_')[3], 'value' : val1})
635                             sur_name_read['store_ans'][resp_id].update({key1:val1})
636                             select_count += 1
637
638                         elif val1 and key1.split('_')[1] == "otherfield" and key1.split('_')[0] == que_id:
639                             comment_field = True
640                             sur_name_read['store_ans'][resp_id].update({key1:val1})
641                             select_count += 1
642                             surv_name_wiz.write(cr, uid, [context.get('sur_name_id',False)], {'store_ans':sur_name_read['store_ans']})
643                             continue
644
645                         elif val1 and key1.split('_')[1] == "selection" and key1.split('_')[0] == que_id:
646                             if len(key1.split('_')) > 2:
647                                 ans_create_id = res_ans_obj.create(cr, uid, {'response_id':resp_id, 'answer_id':key1.split('_')[-1], 'column_id' : val1})
648                                 selected_value.append(val1)
649                                 response_list.append(str(ans_create_id) + "_" + str(key1.split('_')[-1]))
650                             else:
651                                 ans_create_id = res_ans_obj.create(cr, uid, {'response_id':resp_id, 'answer_id':val1})
652                             sur_name_read['store_ans'][resp_id].update({key1:val1})
653                             select_count += 1
654
655                         elif key1.split('_')[1] == "other" and key1.split('_')[0] == que_id:
656                             if not val1:
657                                 comment_value = True
658                             else:
659                                 error = False
660                                 if que_rec['is_comment_require'] and que_rec['comment_valid_type'] == 'must_be_specific_length':
661                                     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                                         error = True
663                                 elif que_rec['is_comment_require'] and  que_rec['comment_valid_type'] in ['must_be_whole_number', 'must_be_decimal_number', 'must_be_date']:
664                                     error = False
665                                     try:
666                                         if que_rec['comment_valid_type'] == 'must_be_whole_number':
667                                             value = int(val1)
668                                             if value <  que_rec['comment_minimum_no'] or value > que_rec['comment_maximum_no']:
669                                                 error = True
670                                         elif que_rec['comment_valid_type'] == 'must_be_decimal_number':
671                                             value = float(val1)
672                                             if value <  que_rec['comment_minimum_float'] or value > que_rec['comment_maximum_float']:
673                                                 error = True
674                                         elif que_rec['comment_valid_type'] == 'must_be_date':
675                                             value = datetime.datetime.strptime(val1, "%Y-%m-%d")
676                                             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"):
677                                                 error = True
678                                     except:
679                                         error = True
680                                 elif que_rec['is_comment_require'] and  que_rec['comment_valid_type'] == 'must_be_email_address':
681                                     import re
682                                     if re.match("^[a-zA-Z0-9._%-+]+@[a-zA-Z0-9._%-]+.[a-zA-Z]{2,6}$", val1) == None:
683                                             error = True
684                                 if error:
685                                     for res in resp_id_list:
686                                         sur_name_read['store_ans'].pop(res)
687                                     raise osv.except_osv(_('Warning!'), "'" + que_rec['question'] + "'  \n" + tools.ustr(que_rec['comment_valid_err_msg']))
688
689                                 resp_obj.write(cr, uid, resp_id, {'comment':val1})
690                                 sur_name_read['store_ans'][resp_id].update({key1:val1})
691
692                         elif val1 and key1.split('_')[1] == "comment" and key1.split('_')[0] == que_id:
693                             resp_obj.write(cr, uid, resp_id, {'comment':val1})
694                             sur_name_read['store_ans'][resp_id].update({key1:val1})
695                             select_count += 1
696
697                         elif val1 and key1.split('_')[0] == que_id and (key1.split('_')[1] == "single"  or (len(key1.split('_')) > 2 and key1.split('_')[2] == 'multi')):
698                             error = False
699                             if que_rec['is_validation_require'] and que_rec['validation_type'] == 'must_be_specific_length':
700                                 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                                     error = True
702                             elif que_rec['is_validation_require'] and que_rec['validation_type'] in ['must_be_whole_number', 'must_be_decimal_number', 'must_be_date']:
703                                 error = False
704                                 try:
705                                     if que_rec['validation_type'] == 'must_be_whole_number':
706                                         value = int(val1)
707                                         if value <  que_rec['validation_minimum_no'] or value > que_rec['validation_maximum_no']:
708                                             error = True
709                                     elif que_rec['validation_type'] == 'must_be_decimal_number':
710                                         value = float(val1)
711                                         if value <  que_rec['validation_minimum_float'] or value > que_rec['validation_maximum_float']:
712                                             error = True
713                                     elif que_rec['validation_type'] == 'must_be_date':
714                                         value = datetime.datetime.strptime(val1, "%Y-%m-%d")
715                                         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"):
716                                             error = True
717                                 except:
718                                     error = True
719                             elif que_rec['is_validation_require'] and que_rec['validation_type'] == 'must_be_email_address':
720                                 import re
721                                 if re.match("^[a-zA-Z0-9._%-+]+@[a-zA-Z0-9._%-]+.[a-zA-Z]{2,6}$", val1) == None:
722                                         error = True
723                             if error:
724                                 for res in resp_id_list:
725                                     sur_name_read['store_ans'].pop(res)
726                                 raise osv.except_osv(_('Warning!'), "'" + que_rec['question'] + "'  \n" + tools.ustr(que_rec['validation_valid_err_msg']))
727
728                             if key1.split('_')[1] == "single" :
729                                 resp_obj.write(cr, uid, resp_id, {'single_text':val1})
730                             else:
731                                 ans_create_id = res_ans_obj.create(cr, uid, {'response_id':resp_id, 'answer_id':key1.split('_')[1], 'answer' : val1})
732
733                             sur_name_read['store_ans'][resp_id].update({key1:val1})
734                             select_count += 1
735
736                         elif val1 and que_id == key1.split('_')[0] and len(key1.split('_')) > 2 and key1.split('_')[2] == 'numeric':
737                             if not val1=="0":
738                                 try:
739                                     numeric_sum += int(val1)
740                                     ans_create_id = res_ans_obj.create(cr, uid, {'response_id':resp_id, 'answer_id':key1.split('_')[1], 'answer' : val1})
741                                     sur_name_read['store_ans'][resp_id].update({key1:val1})
742                                     select_count += 1
743                                 except:
744                                     for res in resp_id_list:
745                                         sur_name_read['store_ans'].pop(res)
746                                     raise osv.except_osv(_('Warning!'), "'" + que_rec['question'] + "' \n" + _("Please enter an integer value."))
747
748                         elif val1 and que_id == key1.split('_')[0] and len(key1.split('_')) == 3:
749                             if type(val1) == type('') or type(val1) == type(u''):
750                                 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})
751                                 sur_name_read['store_ans'][resp_id].update({key1:val1})
752                             else:
753                                 ans_create_id = res_ans_obj.create(cr, uid, {'response_id':resp_id, 'answer_id':key1.split('_')[1], 'column_id' : key1.split('_')[2]})
754                                 sur_name_read['store_ans'][resp_id].update({key1:True})
755
756                             matrix_list.append(key1.split('_')[0] + '_' + key1.split('_')[1])
757                             select_count += 1
758
759                         elif val1 and que_id == key1.split('_')[0] and len(key1.split('_')) == 2:
760                             ans_create_id = res_ans_obj.create(cr, uid, {'response_id':resp_id, 'answer_id':key1.split('_')[-1], 'answer' : val1})
761                             sur_name_read['store_ans'][resp_id].update({key1:val1})
762                             select_count += 1
763                         surv_name_wiz.write(cr, uid, [context.get('sur_name_id',False)], {'store_ans':sur_name_read['store_ans']})
764
765                     for key,val in vals.items():
766                         if val and key.split('_')[1] == "commentcolumn" and key.split('_')[0] == que_id:
767                             for res_id in response_list:
768                                 if key.split('_')[2] in res_id.split('_')[1]:
769                                     a = res_ans_obj.write(cr, uid, [res_id.split('_')[0]], {'comment_field':val})
770                                     sur_name_read['store_ans'][resp_id].update({key:val})
771
772                     if comment_field and comment_value:
773                         for res in resp_id_list:
774                             sur_name_read['store_ans'].pop(res)
775                         raise osv.except_osv(_('Warning!'), "'" + que_rec['question']  + "' " + tools.ustr(que_rec['make_comment_field_err_msg']))
776
777                     if que_rec['type'] == "rating_scale" and que_rec['rating_allow_one_column_require'] and len(selected_value) > len(list(set(selected_value))):
778                         for res in resp_id_list:
779                             sur_name_read['store_ans'].pop(res)
780                         raise osv.except_osv(_('Warning!'), "'" + que_rec['question'] + "'\n" + _("You cannot select the same answer more than one time."))
781
782                     if not select_count:
783                         resp_obj.write(cr, uid, resp_id, {'state':'skip'})
784
785                     if que_rec['numeric_required_sum'] and numeric_sum > que_rec['numeric_required_sum']:
786                         for res in resp_id_list:
787                             sur_name_read['store_ans'].pop(res)
788                         raise osv.except_osv(_('Warning!'), "'" + que_rec['question'] + "' " + tools.ustr(que_rec['numeric_required_sum_err_msg']))
789
790                     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 matrix_list:
792                             if (que_rec['required_type'] == 'all' and len(list(set(matrix_list))) < len(que_rec['answer_choice_ids'])) or \
793                             (que_rec['required_type'] == 'at least' and len(list(set(matrix_list))) < que_rec['req_ans']) or \
794                             (que_rec['required_type'] == 'at most' and len(list(set(matrix_list))) > que_rec['req_ans']) or \
795                             (que_rec['required_type'] == 'exactly' and len(list(set(matrix_list))) != que_rec['req_ans']) or \
796                             (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'])):
797                                 for res in resp_id_list:
798                                     sur_name_read['store_ans'].pop(res)
799                                 raise osv.except_osv(_('Warning!'), "'" + que_rec['question'] + "' " + tools.ustr(que_rec['req_error_msg']))
800
801                         elif (que_rec['required_type'] == 'all' and select_count < len(que_rec['answer_choice_ids'])) or \
802                             (que_rec['required_type'] == 'at least' and select_count < que_rec['req_ans']) or \
803                             (que_rec['required_type'] == 'at most' and select_count > que_rec['req_ans']) or \
804                             (que_rec['required_type'] == 'exactly' and select_count != que_rec['req_ans']) or \
805                             (que_rec['required_type'] == 'a range' and (select_count < que_rec['minimum_req_ans'] or select_count > que_rec['maximum_req_ans'])):
806                             for res in resp_id_list:
807                                 sur_name_read['store_ans'].pop(res)
808                             raise osv.except_osv(_('Warning!'), "'" + que_rec['question'] + "' " + tools.ustr(que_rec['req_error_msg']))
809
810                     if que_rec['type'] in ['multiple_choice_only_one_ans','single_textbox','comment'] and  que_rec['is_require_answer'] and select_count <= 0:
811                         for res in resp_id_list:
812                             sur_name_read['store_ans'].pop(res)
813                         raise osv.except_osv(_('Warning!'), "'" + que_rec['question'] + "' " + tools.ustr(que_rec['req_error_msg']))
814
815         else:
816             resp_id_list = []
817             for update in click_update:
818                 que_rec = que_obj.read(cr, uid , [int(sur_name_read['store_ans'][update]['question_id'])], [])[0]
819                 res_ans_obj.unlink(cr, uid,res_ans_obj.search(cr, uid, [('response_id', '=', update)]))
820                 surv_tbl_column_obj.unlink(cr, uid,surv_tbl_column_obj.search(cr, uid, [('response_table_id', '=', update)]))
821                 resp_id_list.append(update)
822                 sur_name_read['store_ans'].update({update:{'question_id':sur_name_read['store_ans'][update]['question_id']}})
823                 surv_name_wiz.write(cr, uid, [context.get('sur_name_id',False)], {'store_ans':sur_name_read['store_ans']})
824                 select_count = 0
825                 numeric_sum = 0
826                 selected_value = []
827                 matrix_list = []
828                 comment_field = False
829                 comment_value = False
830                 response_list = []
831
832                 for key, val in vals.items():
833                     ans_id_len = key.split('_')
834                     if ans_id_len[0] == sur_name_read['store_ans'][update]['question_id']:
835                         if val and key.split('_')[1] == "table":
836                             surv_tbl_column_obj.create(cr, uid, {'response_table_id' : update,'column_id':key.split('_')[2], 'name':key.split('_')[3], 'value' : val})
837                             sur_name_read['store_ans'][update].update({key:val})
838                             resp_obj.write(cr, uid, update, {'state': 'done'})
839
840                         elif val and key.split('_')[1] == "otherfield" :
841                             comment_field = True
842                             sur_name_read['store_ans'][update].update({key:val})
843                             select_count += 1
844                             surv_name_wiz.write(cr, uid, [context.get('sur_name_id',False)], {'store_ans':sur_name_read['store_ans']})
845                             continue
846
847                         elif val and key.split('_')[1] == "selection":
848                             if len(key.split('_')) > 2:
849                                 ans_create_id = res_ans_obj.create(cr, uid, {'response_id':update, 'answer_id':key.split('_')[-1], 'column_id' : val})
850                                 selected_value.append(val)
851                                 response_list.append(str(ans_create_id) + "_" + str(key.split('_')[-1]))
852                             else:
853                                 ans_create_id = res_ans_obj.create(cr, uid, {'response_id':update, 'answer_id': val})
854                             resp_obj.write(cr, uid, update, {'state': 'done'})
855                             sur_name_read['store_ans'][update].update({key:val})
856                             select_count += 1
857
858                         elif key.split('_')[1] == "other":
859                             if not val:
860                                 comment_value = True
861                             else:
862                                 error = False
863                                 if que_rec['is_comment_require'] and  que_rec['comment_valid_type'] == 'must_be_specific_length':
864                                     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                                         error = True
866                                 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                                     try:
868                                         if que_rec['comment_valid_type'] == 'must_be_whole_number':
869                                             value = int(val)
870                                             if value <  que_rec['comment_minimum_no'] or value > que_rec['comment_maximum_no']:
871                                                 error = True
872                                         elif que_rec['comment_valid_type'] == 'must_be_decimal_number':
873                                             value = float(val)
874                                             if value <  que_rec['comment_minimum_float'] or value > que_rec['comment_maximum_float']:
875                                                 error = True
876                                         elif que_rec['comment_valid_type'] == 'must_be_date':
877                                             value = datetime.datetime.strptime(val, "%Y-%m-%d")
878                                             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"):
879                                                 error = True
880                                     except:
881                                         error = True
882                                 elif que_rec['is_comment_require'] and  que_rec['comment_valid_type'] == 'must_be_email_address':
883                                     import re
884                                     if re.match("^[a-zA-Z0-9._%-+]+@[a-zA-Z0-9._%-]+.[a-zA-Z]{2,6}$", val) == None:
885                                             error = True
886                                 if error:
887                                     raise osv.except_osv(_('Warning!'), "'" + que_rec['question'] + "'  \n" + tools.ustr(que_rec['comment_valid_err_msg']))
888                                 resp_obj.write(cr, uid, update, {'comment':val,'state': 'done'})
889                                 sur_name_read['store_ans'][update].update({key:val})
890
891                         elif val and key.split('_')[1] == "comment":
892                             resp_obj.write(cr, uid, update, {'comment':val,'state': 'done'})
893                             sur_name_read['store_ans'][update].update({key:val})
894                             select_count += 1
895
896                         elif val and (key.split('_')[1] == "single"  or (len(key.split('_')) > 2 and key.split('_')[2] == 'multi')):
897                             error = False
898                             if que_rec['is_validation_require'] and que_rec['validation_type'] == 'must_be_specific_length':
899                                 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                                     error = True
901                             elif que_rec['is_validation_require'] and que_rec['validation_type'] in ['must_be_whole_number', 'must_be_decimal_number', 'must_be_date']:
902                                 error = False
903                                 try:
904                                     if que_rec['validation_type'] == 'must_be_whole_number':
905                                         value = int(val)
906                                         if value <  que_rec['validation_minimum_no'] or value > que_rec['validation_maximum_no']:
907                                             error = True
908                                     elif que_rec['validation_type'] == 'must_be_decimal_number':
909                                         value = float(val)
910                                         if value <  que_rec['validation_minimum_float'] or value > que_rec['validation_maximum_float']:
911                                             error = True
912                                     elif que_rec['validation_type'] == 'must_be_date':
913                                         value = datetime.datetime.strptime(val, "%Y-%m-%d")
914                                         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"):
915                                             error = True
916                                 except Exception ,e:
917                                     error = True
918                             elif que_rec['is_validation_require'] and  que_rec['validation_type'] == 'must_be_email_address':
919                                 import re
920                                 if re.match("^[a-zA-Z0-9._%-+]+@[a-zA-Z0-9._%-]+.[a-zA-Z]{2,6}$", val) == None:
921                                         error = True
922                             if error:
923                                 raise osv.except_osv(_('Warning!'), "'" + que_rec['question'] + "'  \n" + tools.ustr(que_rec['validation_valid_err_msg']))
924                             if key.split('_')[1] == "single" :
925                                 resp_obj.write(cr, uid, update, {'single_text':val,'state': 'done'})
926                             else:
927                                 resp_obj.write(cr, uid, update, {'state': 'done'})
928                                 ans_create_id = res_ans_obj.create(cr, uid, {'response_id':update, 'answer_id':ans_id_len[1], 'answer' : val})
929                             sur_name_read['store_ans'][update].update({key:val})
930                             select_count += 1
931
932                         elif val and len(key.split('_')) > 2 and key.split('_')[2] == 'numeric':
933                             if not val=="0":
934                                 try:
935                                     numeric_sum += int(val)
936                                     resp_obj.write(cr, uid, update, {'state': 'done'})
937                                     ans_create_id = res_ans_obj.create(cr, uid, {'response_id': update, 'answer_id':ans_id_len[1], 'answer' : val})
938                                     sur_name_read['store_ans'][update].update({key:val})
939                                     select_count += 1
940                                 except:
941                                     raise osv.except_osv(_('Warning!'), "'" + que_rec['question'] + "'\n" + _("Please enter an integer value."))
942
943                         elif val and len(key.split('_')) == 3:
944                             resp_obj.write(cr, uid, update, {'state': 'done'})
945                             if type(val) == type('') or type(val) == type(u''):
946                                 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})
947                                 sur_name_read['store_ans'][update].update({key:val})
948                             else:
949                                 ans_create_id = res_ans_obj.create(cr, uid, {'response_id': update, 'answer_id':ans_id_len[1], 'column_id' : ans_id_len[2]})
950                                 sur_name_read['store_ans'][update].update({key:True})
951                             matrix_list.append(key.split('_')[0] + '_' + key.split('_')[1])
952                             select_count += 1
953
954                         elif val and len(key.split('_')) == 2:
955                             resp_obj.write(cr, uid, update, {'state': 'done'})
956                             ans_create_id = res_ans_obj.create(cr, uid, {'response_id': update, 'answer_id':ans_id_len[-1], 'answer' : val})
957                             sur_name_read['store_ans'][update].update({key:val})
958                             select_count += 1
959                         surv_name_wiz.write(cr, uid, [context.get('sur_name_id',False)], {'store_ans': sur_name_read['store_ans']})
960
961                 for key,val in vals.items():
962                     if val and key.split('_')[1] == "commentcolumn" and key.split('_')[0] == sur_name_read['store_ans'][update]['question_id']:
963                         for res_id in response_list:
964                             if key.split('_')[2] in res_id.split('_')[1]:
965                                 a = res_ans_obj.write(cr, uid, [res_id.split('_')[0]], {'comment_field':val})
966                                 sur_name_read['store_ans'][update].update({key:val})
967
968                 if comment_field and comment_value:
969                     raise osv.except_osv(_('Warning!'), "'" + que_rec['question']  + "' " + tools.ustr(que_rec['make_comment_field_err_msg']))
970
971                 if que_rec['type'] == "rating_scale" and que_rec['rating_allow_one_column_require'] and len(selected_value) > len(list(set(selected_value))):
972                     raise osv.except_osv(_('Warning!'), "'" + que_rec['question'] + "\n" + _("You cannot select same answer more than one time.'"))
973
974                 if que_rec['numeric_required_sum'] and numeric_sum > que_rec['numeric_required_sum']:
975                     raise osv.except_osv(_('Warning!'), "'" + que_rec['question'] + "' " + tools.ustr(que_rec['numeric_required_sum_err_msg']))
976
977                 if not select_count:
978                     resp_obj.write(cr, uid, update, {'state': 'skip'})
979
980                 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 matrix_list:
982                         if (que_rec['required_type'] == 'all' and len(list(set(matrix_list))) < len(que_rec['answer_choice_ids'])) or \
983                         (que_rec['required_type'] == 'at least' and len(list(set(matrix_list))) < que_rec['req_ans']) or \
984                         (que_rec['required_type'] == 'at most' and len(list(set(matrix_list))) > que_rec['req_ans']) or \
985                         (que_rec['required_type'] == 'exactly' and len(list(set(matrix_list))) != que_rec['req_ans']) or \
986                         (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'])):
987                             raise osv.except_osv(_('Warning!'), "'" + que_rec['question'] + "' " + tools.ustr(que_rec['req_error_msg']))
988
989                     elif (que_rec['required_type'] == 'all' and select_count < len(que_rec['answer_choice_ids'])) or \
990                         (que_rec['required_type'] == 'at least' and select_count < que_rec['req_ans']) or \
991                         (que_rec['required_type'] == 'at most' and select_count > que_rec['req_ans']) or \
992                         (que_rec['required_type'] == 'exactly' and select_count != que_rec['req_ans']) or \
993                         (que_rec['required_type'] == 'a range' and (select_count < que_rec['minimum_req_ans'] or select_count > que_rec['maximum_req_ans'])):
994                             raise osv.except_osv(_('Warning!'), "'" + que_rec['question'] + "' " + tools.ustr(que_rec['req_error_msg']))
995
996                 if que_rec['type'] in ['multiple_choice_only_one_ans','single_textbox','comment'] and  que_rec['is_require_answer'] and select_count <= 0:
997                     raise osv.except_osv(_('Warning!'), "'" + que_rec['question'] + "' " + tools.ustr(que_rec['req_error_msg']))
998
999         return survey_question_wiz_id
1000
1001     def action_new_question(self,cr, uid, ids, context=None):
1002         """
1003         New survey.Question form.
1004         """
1005         if context is None:
1006             context = {}
1007         for key,val in context.items():
1008             if type(key) == type(True):
1009                 context.pop(key)
1010         view_id = self.pool.get('ir.ui.view').search(cr,uid,[('model','=','survey.question'),\
1011                             ('name','=','survey_question_wizard_test')])
1012         return {
1013             'view_type': 'form',
1014             "view_mode": 'form',
1015             'res_model': 'survey.question',
1016             'type': 'ir.actions.act_window',
1017             'target': 'new',
1018             'view_id': view_id,
1019             'context': context
1020         }
1021
1022     def action_new_page(self, cr, uid, ids, context=None):
1023         """
1024         New survey.Page form.
1025         """
1026         if context is None:
1027             context = {}
1028         for key,val in context.items():
1029             if type(key) == type(True):
1030                 context.pop(key)
1031         view_id = self.pool.get('ir.ui.view').search(cr,uid,[('model','=','survey.page'),\
1032                                         ('name','=','survey_page_wizard_test')])
1033         return {
1034             'view_type': 'form',
1035             "view_mode": 'form',
1036             'res_model': 'survey.page',
1037             'type': 'ir.actions.act_window',
1038             'target': 'new',
1039             'view_id': view_id,
1040             'context': context
1041         }
1042
1043     def action_edit_page(self,cr, uid, ids, context=None):
1044         """
1045         Edit survey.page.
1046         """
1047         if context is None:
1048             context = {}
1049         for key,val in context.items():
1050             if type(key) == type(True):
1051                 context.pop(key)
1052         view_id = self.pool.get('ir.ui.view').search(cr,uid,[('model','=','survey.page'),\
1053                                 ('name','=','survey_page_wizard_test')])
1054         return {
1055             'view_type': 'form',
1056             "view_mode": 'form',
1057             'res_model': 'survey.page',
1058             'type': 'ir.actions.act_window',
1059             'target': 'new',
1060             'res_id': int(context.get('page_id',0)),
1061             'view_id': view_id,
1062             'context': context
1063         }
1064
1065     def action_delete_page(self,cr, uid, ids, context=None):
1066         """
1067         Delete survey.page.
1068         """
1069         if context is None:
1070             context = {}
1071         for key,val in context.items():
1072             if type(key) == type(True):
1073                 context.pop(key)
1074
1075         self.pool.get('survey.page').unlink(cr, uid, [context.get('page_id',False)])
1076         search_id = self.pool.get('ir.ui.view').search(cr,uid,[('model','=','survey.question.wiz'),\
1077                                             ('name','=','Survey Search')])
1078         surv_name_wiz = self.pool.get('survey.name.wiz')
1079         surv_name_wiz.write(cr, uid, [context.get('sur_name_id',False)], \
1080                     {'transfer':True, 'page_no' : context.get('page_number',False) })
1081         return {
1082             'view_type': 'form',
1083             "view_mode": 'form',
1084             'res_model': 'survey.question.wiz',
1085             'type': 'ir.actions.act_window',
1086             'target': 'new',
1087             'search_view_id':search_id[0],
1088             'context': context
1089         }
1090
1091     def action_edit_question(self,cr, uid, ids, context=None):
1092         """
1093         Edit survey.question.
1094         """
1095         if context is None:
1096             context = {}
1097         for key,val in context.items():
1098             if type(key) == type(True):
1099                 context.pop(key)
1100         view_id = self.pool.get('ir.ui.view').search(cr,uid,[('model','=','survey.question'),\
1101                                 ('name','=','survey_question_wizard_test')])
1102         return {
1103             'view_type': 'form',
1104             "view_mode": 'form',
1105             'res_model': 'survey.question',
1106             'type': 'ir.actions.act_window',
1107             'target': 'new',
1108             'res_id' : int(context.get('question_id',0)),
1109             'view_id': view_id,
1110             'context': context
1111         }
1112
1113     def action_delete_question(self,cr, uid, ids, context=None):
1114         """
1115         Delete survey.question.
1116         """
1117         if context is None:
1118             context = {}
1119         for key,val in context.items():
1120             if type(key) == type(True):
1121                 context.pop(key)
1122
1123         que_obj = self.pool.get('survey.question')
1124         que_obj.unlink(cr, uid, [context.get('question_id',False)])
1125         search_id = self.pool.get('ir.ui.view').search(cr,uid,[('model','=','survey.question.wiz'),\
1126                                         ('name','=','Survey Search')])
1127         surv_name_wiz = self.pool.get('survey.name.wiz')
1128         surv_name_wiz.write(cr, uid, [context.get('sur_name_id',False)],\
1129                      {'transfer':True, 'page_no' : context.get('page_number',0) })
1130         return {
1131                 'view_type': 'form',
1132                 "view_mode": 'form',
1133                 'res_model': 'survey.question.wiz',
1134                 'type': 'ir.actions.act_window',
1135                 'target': 'new',
1136                 'search_view_id': search_id[0],
1137                 'context': context
1138                 }
1139
1140     def action_forward_previous(self, cr, uid, ids, context=None):
1141         """
1142         Goes to previous Survey Answer.
1143         """
1144         if context is None:
1145             context = {}
1146         search_obj = self.pool.get('ir.ui.view')
1147         surv_name_wiz = self.pool.get('survey.name.wiz')
1148         search_id = search_obj.search(cr,uid,[('model','=','survey.question.wiz'),\
1149                                               ('name','=','Survey Search')])
1150         wiz_id = surv_name_wiz.create(cr,uid, {'survey_id': context.get('survey_id',False),'page_no' :-1,'page':'next','transfer' :1,'response':0})
1151         context.update({'sur_name_id' :wiz_id, 'response_no': context.get('response_no',0) - 1})
1152
1153         if context.get('response_no',0) + 1 > len(context.get('response_id',0)):
1154             return {}
1155         return {
1156             'view_type': 'form',
1157             "view_mode": 'form',
1158             'res_model': 'survey.question.wiz',
1159             'type': 'ir.actions.act_window',
1160             'target': 'new',
1161             'search_view_id': search_id[0],
1162             'context': context
1163         }
1164
1165     def action_forward_next(self, cr, uid, ids, context=None):
1166         """
1167         Goes to Next Survey Answer.
1168         """
1169         if context is None:
1170             context = {}
1171         search_obj = self.pool.get('ir.ui.view')
1172         surv_name_wiz = self.pool.get('survey.name.wiz')
1173         search_id = search_obj.search(cr,uid,[('model','=','survey.question.wiz'),\
1174                                     ('name','=','Survey Search')])
1175         wiz_id = surv_name_wiz.create(cr,uid, {'survey_id' : context.get('survey_id',False),'page_no' :-1,'page':'next','transfer' :1,'response':0})
1176         context.update({'sur_name_id' :wiz_id, 'response_no' : context.get('response_no',0) + 1})
1177
1178         if context.get('response_no',0) + 1 > len(context.get('response_id',0)):
1179             return {}
1180         return {
1181             'view_type': 'form',
1182             "view_mode": 'form',
1183             'res_model': 'survey.question.wiz',
1184             'type': 'ir.actions.act_window',
1185             'target': 'new',
1186             'search_view_id': search_id[0],
1187             'context': context
1188         }
1189
1190     def action_next(self, cr, uid, ids, context=None):
1191         """
1192         Goes to Next page.
1193         """
1194         if context is None:
1195             context = {}
1196         surv_name_wiz = self.pool.get('survey.name.wiz')
1197         search_obj = self.pool.get('ir.ui.view')
1198         search_id = search_obj.search(cr,uid,[('model','=','survey.question.wiz'),('name','=','Survey Search')])
1199         surv_name_wiz.write(cr, uid, [context.get('sur_name_id',False)], {'transfer':True, 'page':'next'})
1200         return {
1201             'view_type': 'form',
1202             "view_mode": 'form',
1203             'res_model': 'survey.question.wiz',
1204             'type': 'ir.actions.act_window',
1205             'target': 'new',
1206             'search_view_id': search_id[0],
1207             'context': context
1208         }
1209
1210     def action_previous(self, cr, uid, ids, context=None):
1211         """
1212         Goes to previous page.
1213         """
1214         if context is None:
1215             context = {}
1216         surv_name_wiz = self.pool.get('survey.name.wiz')
1217         search_obj = self.pool.get('ir.ui.view')
1218         search_id = search_obj.search(cr,uid,[('model','=','survey.question.wiz'),\
1219                                     ('name','=','Survey Search')])
1220         surv_name_wiz.write(cr, uid, [context.get('sur_name_id',False)], {'transfer':True, 'page':'previous'})
1221         return {
1222             'view_type': 'form',
1223             "view_mode": 'form',
1224             'res_model': 'survey.question.wiz',
1225             'type': 'ir.actions.act_window',
1226             'target': 'new',
1227             'search_view_id': search_id[0],
1228             'context': context
1229         }
1230
1231 survey_question_wiz()
1232
1233 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: