1 # -*- encoding: utf-8 -*-
2 ##############################################################################
4 # OpenERP, Open Source Management Solution
5 # Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
8 # This program is free software: you can redistribute it and/or modify
9 # it under the terms of the GNU General Public License as published by
10 # the Free Software Foundation, either version 3 of the License, or
11 # (at your option) any later version.
13 # This program is distributed in the hope that it will be useful,
14 # but WITHOUT ANY WARRANTY; without even the implied warranty of
15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 # GNU General Public License for more details.
18 # You should have received a copy of the GNU General Public License
19 # along with this program. If not, see <http://www.gnu.org/licenses/>.
21 ##############################################################################
24 from lxml import etree
25 from time import strftime
30 from osv import fields
31 from tools import to_xml
32 from tools.translate import _
34 class survey_question_wiz(osv.osv_memory):
35 _name = 'survey.question.wiz'
37 'name': fields.integer('Number'),
40 def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
42 Fields View Get method :- generate the new view and display the survey pages of selected survey.
44 @param self: The object pointer
45 @param cr: the current row, from the database cursor,
46 @param uid: the current user’s ID for security checks,
47 @param view_id : view id of the current object.
48 @param view_type : which type of view is create. like :- form, tree ,search etc...
49 @param context: A standard dictionary for contextual values
50 @return : Dictionary value for created view of particular survey pages.
53 result = super(survey_question_wiz, self).fields_view_get(cr, uid, view_id, \
54 view_type, context, toolbar,submenu)
56 surv_name_wiz = self.pool.get('survey.name.wiz')
57 survey_obj = self.pool.get('survey')
58 page_obj = self.pool.get('survey.page')
59 que_obj = self.pool.get('survey.question')
60 ans_obj = self.pool.get('survey.answer')
61 sur_response_obj = self.pool.get('survey.response')
62 que_col_head = self.pool.get('survey.question.column.heading')
63 user_obj = self.pool.get('res.users')
65 if view_type in ['form']:
67 if not context.has_key('sur_name_id'):
69 'survey_id': context.get('survey_id', False),
75 wiz_id = surv_name_wiz.create(cr, uid, res_data)
76 sur_name_rec = surv_name_wiz.browse(cr, uid, wiz_id)
77 context.update({'sur_name_id' :wiz_id})
79 sur_name_rec = surv_name_wiz.browse(cr, uid, context['sur_name_id'])
81 if context.has_key('active_id'):
82 context.pop('active_id')
84 survey_id = context.get('survey_id', False)
86 # Try one more time to find it
87 if sur_name_rec.survey_id:
88 survey_id = sur_name_rec.survey_id[0]
90 # raise osv.except_osv(_('Error!'), _("Cannot locate survey for the question wizard!"))
91 # If this function is called without a survey_id in
92 # its context, it makes no sense to return any view.
93 # Just return the default, empty view for this object,
94 # in order to please random calls to this fn().
95 return super(survey_question_wiz, self).\
96 fields_view_get(cr, uid, view_id=view_id, view_type=view_type, context=context,
97 toolbar=toolbar, submenu=submenu)
99 sur_rec = survey_obj.browse(cr, uid, survey_id)
100 p_id = map(lambda x:x.id, sur_rec.page_ids)
101 total_pages = len(p_id)
105 if context.get('response_id', False) \
106 and int(context['response_id'][0]) > 0:
109 if not sur_name_rec.page_no + 1 :
110 surv_name_wiz.write(cr, uid, [context['sur_name_id'],], {'store_ans':{}})
112 sur_name_read = surv_name_wiz.browse(cr, uid, context['sur_name_id'])
113 page_number = int(sur_name_rec.page_no)
114 if sur_name_read.transfer or not sur_name_rec.page_no + 1:
115 surv_name_wiz.write(cr, uid, [context['sur_name_id']], {'transfer':False})
118 if sur_name_read.page == "next" or sur_name_rec.page_no == -1:
119 if total_pages > sur_name_rec.page_no + 1:
120 if ((context.has_key('active') and not context.get('active', False)) \
121 or not context.has_key('active')) and not sur_name_rec.page_no + 1:
122 if sur_rec.state != "open" :
123 raise osv.except_osv(_('Warning !'),_("You can not give answer because of survey is not open for answer"))
124 cr.execute('select count(id) from survey_history where user_id=%s\
125 and survey_id=%s', (uid,survey_id))
126 res = cr.fetchone()[0]
127 user_limit = survey_obj.browse(cr, uid, survey_id)
128 user_limit = user_limit.response_user
129 if user_limit and res >= user_limit:
130 raise osv.except_osv(_('Warning !'),_("You can not give answer for this survey more than %s times") % (user_limit))
132 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:
133 survey_obj.write(cr, uid, survey_id, {'state':'close', 'date_close':strftime("%Y-%m-%d %H:%M:%S")})
135 p_id = p_id[sur_name_rec.page_no + 1]
136 surv_name_wiz.write(cr, uid, [context['sur_name_id'],], {'page_no' : sur_name_rec.page_no + 1})
139 if sur_name_rec.page_no > - 1:
142 if sur_name_rec.page_no != 0:
143 p_id = p_id[sur_name_rec.page_no - 1]
144 surv_name_wiz.write(cr, uid, [context['sur_name_id'],],\
145 {'page_no' : sur_name_rec.page_no - 1})
149 if sur_name_rec.page_no > 1:
152 pag_rec = page_obj.browse(cr, uid, p_id)
153 xml_form = etree.Element('form', {'string': _(tools.ustr(pag_rec.title))})
154 xml_group = etree.SubElement(xml_form, 'group', {'col': '1', 'colspan': '4'})
155 if context.has_key('response_id') and context.get('response_id', False) \
156 and int(context.get('response_id',0)[0]) > 0:
157 # TODO: l10n, cleanup this code to make it readable. Or template?
158 xml_group = etree.SubElement(xml_form, 'group', {'col': '40', 'colspan': '4'})
159 record = sur_response_obj.browse(cr, uid, context['response_id'][context['response_no']])
160 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"})
161 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"})
162 if context.get('response_no',0) > 0:
163 etree.SubElement(xml_group, 'button', {'colspan':"1",'icon':"gtk-go-back",'name':"action_forward_previous",'string': tools.ustr("Previous Answer"),'type':"object"})
164 if context.get('response_no',0) + 1 < len(context.get('response_id',0)):
165 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)})
168 fields["wizardid_" + str(wiz_id)] = {'type':'char', 'size' : 255, 'string':"", 'views':{}}
169 etree.SubElement(xml_form, 'field', {'invisible':'1','name': "wizardid_" + str(wiz_id),'default':str(lambda *a: 0)})
172 xml_group = etree.SubElement(xml_form, 'group', {'col': '1', 'colspan': '4'})
173 for que_test in pag_rec.note.split('\n'):
174 etree.SubElement(xml_group, 'label', {'string': to_xml(tools.ustr(que_test)), 'align':"0.0"})
175 que_ids = pag_rec.question_ids
180 que_rec = que_obj.browse(cr, uid, que.id)
181 descriptive_text = ""
182 separator_string = tools.ustr(qu_no) + "." + tools.ustr(que_rec.question)
183 if ((context.has_key('active') and not context.get('active',False)) or not context.has_key('active')) and que_rec.is_require_answer:
187 xml_group = etree.SubElement(xml_form, 'group', {'col': '2', 'colspan': '4'})
189 if context.has_key('active') and context.get('active',False) and \
190 context.has_key('edit'):
191 xml_group = etree.SubElement(xml_form, 'group', {'col': '1', 'colspan': '2'})
192 etree.SubElement(xml_group, 'separator', {'string': star+to_xml(separator_string), 'colspan': '3'})
193 xml_group1 = etree.SubElement(xml_form, 'group', {'col': '2', 'colspan': '2'})
194 context.update({'question_id' : tools.ustr(que.id),'page_number': sur_name_rec.page_no , 'transfer' : sur_name_read.transfer, 'page_id' : p_id})
195 etree.SubElement(xml_group1, 'button', {'string':'','icon': "gtk-edit", 'type' :'object', 'name':"action_edit_question", 'context' : tools.ustr(context)})
196 etree.SubElement(xml_group1, 'button', {'string':'','icon': "gtk-delete", 'type' :'object','name':"action_delete_question", 'context' : tools.ustr(context)})
198 xml_group = etree.SubElement(xml_form, 'group', {'col': '1', 'colspan': '4'})
199 etree.SubElement(xml_group, 'separator', {'string': star+to_xml(separator_string), 'colspan': '4'})
201 ans_ids = que_rec.answer_choice_ids
202 xml_group = etree.SubElement(xml_form, 'group', {'col': '1', 'colspan': '4'})
204 if que_rec.type == 'multiple_choice_only_one_ans':
207 selection.append((tools.ustr(ans.id), ans.answer))
208 xml_group = etree.SubElement(xml_group, 'group', {'col': '2', 'colspan': '2'})
209 etree.SubElement(xml_group, 'field', {'readonly':str(readonly), 'name': tools.ustr(que.id) + "_selection"})
210 fields[tools.ustr(que.id) + "_selection"] = {'type':'selection', 'selection' :selection, 'string':"Answer"}
212 elif que_rec.type == 'multiple_choice_multiple_ans':
213 xml_group = etree.SubElement(xml_group, 'group', {'col': '4', 'colspan': '4'})
215 etree.SubElement(xml_group, 'field', {'readonly':str(readonly), 'name': tools.ustr(que.id) + "_" + tools.ustr(ans.id)})
216 fields[tools.ustr(que.id) + "_" + tools.ustr(ans.id)] = {'type':'boolean', 'string':ans.answer}
218 elif que_rec.type in ['matrix_of_choices_only_one_ans', 'rating_scale']:
219 if que_rec.comment_column:
225 xml_group = etree.SubElement(xml_group, 'group', {'col': tools.ustr(col), 'colspan': tools.ustr(colspan)})
227 etree.SubElement(xml_group, 'newline')
228 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))})
229 selection = [('','')]
230 for col in que_rec.column_heading_ids:
231 selection.append((str(col.id), col.title))
232 fields[tools.ustr(que.id) + "_selection_" + tools.ustr(row.id)] = {'type':'selection', 'selection' : selection, 'string': "Answer"}
233 if que_rec.comment_column:
234 fields[tools.ustr(que.id) + "_commentcolumn_"+tools.ustr(row.id) + "_field"] = {'type':'char', 'size' : 255, 'string':tools.ustr(que_rec.column_name), 'views':{}}
235 etree.SubElement(xml_group, 'field', {'readonly' :str(readonly), 'name': tools.ustr(que.id) + "_commentcolumn_"+tools.ustr(row.id)+ "_field"})
237 elif que_rec.type == 'matrix_of_choices_only_multi_ans':
238 xml_group = etree.SubElement(xml_group, 'group', {'col': str(len(que_rec.column_heading_ids) + 1), 'colspan': '4'})
239 etree.SubElement(xml_group, 'separator', {'string': '.','colspan': '1'})
240 for col in que_rec.column_heading_ids:
241 etree.SubElement(xml_group, 'separator', {'string': tools.ustr(col.title),'colspan': '1'})
243 etree.SubElement(xml_group, 'label', {'string': to_xml(tools.ustr(row.answer)) +' :-', 'align': '0.0'})
244 for col in que_col_head.read(cr, uid, que_rec.column_heading_ids):
245 etree.SubElement(xml_group, 'field', {'readonly' :str(readonly), 'name': tools.ustr(que.id) + "_" + tools.ustr(row.id) + "_" + tools.ustr(col.id), 'nolabel':"1"})
246 fields[tools.ustr(que.id) + "_" + tools.ustr(row.id) + "_" + tools.ustr(col.id)] = {'type':'boolean', 'string': col.title}
248 elif que_rec.type == 'matrix_of_drop_down_menus':
249 xml_group = etree.SubElement(xml_group, 'group', {'col': str(len(que_rec.column_heading_ids) + 1), 'colspan': '4'})
250 etree.SubElement(xml_group, 'separator', {'string': '.','colspan': '1'})
251 for col in que_rec.column_heading_ids:
252 etree.SubElement(xml_group, 'separator', {'string': tools.ustr(col.title),'colspan': '1'})
254 etree.SubElement(xml_group, 'label', {'string': to_xml(tools.ustr(row.answer))+' :-', 'align': '0.0'})
255 for col in que_rec.column_heading_ids:
258 for item in col.menu_choice.split('\n'):
259 if item and not item.strip() == '': selection.append((item ,item))
260 etree.SubElement(xml_group, 'field', {'readonly' :str(readonly), 'name': tools.ustr(que.id) + "_" + tools.ustr(row.id) + "_" + tools.ustr(col.id),'nolabel':'1'})
261 fields[tools.ustr(que.id) + "_" + tools.ustr(row.id) + "_" + tools.ustr(col.id)] = {'type':'selection', 'string': col.title, 'selection':selection}
263 elif que_rec.type == 'multiple_textboxes':
264 xml_group = etree.SubElement(xml_group, 'group', {'col': '4', 'colspan': '4'})
266 if que_rec.is_validation_require:
267 if que_rec.validation_type in ['must_be_whole_number']:
269 elif que_rec.validation_type in ['must_be_decimal_number']:
271 elif que_rec.validation_type in ['must_be_date']:
274 etree.SubElement(xml_group, 'field', {'readonly': str(readonly), 'width':"300",'colspan': '1','name': tools.ustr(que.id) + "_" + tools.ustr(ans.id) + "_multi"})
276 fields[tools.ustr(que.id) + "_" + tools.ustr(ans.id) + "_multi"] = {'type':'char', 'size':255, 'string':ans.answer}
278 fields[tools.ustr(que.id) + "_" + tools.ustr(ans.id) + "_multi"] = {'type': str(type), 'string':ans.answer}
280 elif que_rec.type == 'numerical_textboxes':
281 xml_group = etree.SubElement(xml_group, 'group', {'col': '4', 'colspan': '4'})
283 etree.SubElement(xml_group, 'field', {'readonly': str(readonly), 'width':"300",'colspan': '1','name': tools.ustr(que.id) + "_" + tools.ustr(ans.id) + "_numeric"})
284 fields[tools.ustr(que.id) + "_" + tools.ustr(ans.id) + "_numeric"] = {'type':'integer', 'string':ans.answer}
286 elif que_rec.type == 'date':
287 xml_group = etree.SubElement(xml_group, 'group', {'col': '4', 'colspan': '4'})
289 etree.SubElement(xml_group, 'field', {'readonly': str(readonly), 'width':"300",'colspan': '1','name': tools.ustr(que.id) + "_" + tools.ustr(ans.id)})
290 fields[tools.ustr(que.id) + "_" + tools.ustr(ans.id)] = {'type':'date', 'string':ans.answer}
292 elif que_rec.type == 'date_and_time':
293 xml_group = etree.SubElement(xml_group, 'group', {'col': '4', 'colspan': '4'})
295 etree.SubElement(xml_group, 'field', {'readonly': str(readonly), 'width':"300",'colspan': '1','name': tools.ustr(que.id) + "_" + tools.ustr(ans.id)})
296 fields[tools.ustr(que.id) + "_" + tools.ustr(ans.id)] = {'type':'datetime', 'string':ans.answer}
298 elif que_rec.type == 'descriptive_text':
299 for que_test in que_rec.descriptive_text.split('\n'):
300 etree.SubElement(xml_group, 'label', {'string': to_xml(tools.ustr(que_test)), 'align':"0.0"})
302 elif que_rec.type == 'single_textbox':
303 etree.SubElement(xml_group, 'field', {'readonly' :str(readonly), 'name': tools.ustr(que.id) + "_single", 'nolabel':"1" ,'colspan':"4"})
304 fields[tools.ustr(que.id) + "_single"] = {'type':'char', 'size': 255, 'string':"single_textbox", 'views':{}}
306 elif que_rec.type == 'comment':
307 etree.SubElement(xml_group, 'field', {'readonly' :str(readonly), 'name': tools.ustr(que.id) + "_comment", 'nolabel':"1" ,'colspan':"4"})
308 fields[tools.ustr(que.id) + "_comment"] = {'type':'text', 'string':"Comment/Eassy Box", 'views':{}}
310 elif que_rec.type == 'table':
311 xml_group = etree.SubElement(xml_group, 'group', {'col': str(len(que_rec.column_heading_ids)), 'colspan': '4'})
312 for col in que_rec.column_heading_ids:
313 etree.SubElement(xml_group, 'separator', {'string': tools.ustr(col.title),'colspan': '1'})
314 for row in range(0,que_rec.no_of_rows):
315 for col in que_rec.column_heading_ids:
316 etree.SubElement(xml_group, 'field', {'readonly' :str(readonly), 'name': tools.ustr(que.id) + "_table_" + tools.ustr(col.id) +"_"+ tools.ustr(row), 'nolabel':"1"})
317 fields[tools.ustr(que.id) + "_table_" + tools.ustr(col.id) +"_"+ tools.ustr(row)] = {'type':'char','size':255,'views':{}}
319 elif que_rec.type == 'multiple_textboxes_diff_type':
320 xml_group = etree.SubElement(xml_group, 'group', {'col': '4', 'colspan': '4'})
322 if ans.type == "email" :
323 fields[tools.ustr(que.id) + "_" + tools.ustr(ans.id) + "_multi"] = {'type':'char', 'size':255, 'string':ans.answer}
324 etree.SubElement(xml_group, 'field', {'readonly': str(readonly), 'widget':'email','width':"300",'colspan': '1','name': tools.ustr(que.id) + "_" + tools.ustr(ans.id) + "_multi"})
326 etree.SubElement(xml_group, 'field', {'readonly': str(readonly), 'width':"300",'colspan': '1','name': tools.ustr(que.id) + "_" + tools.ustr(ans.id) + "_multi"})
327 if ans.type == "char" :
328 fields[tools.ustr(que.id) + "_" + tools.ustr(ans.id) + "_multi"] = {'type':'char', 'size':255, 'string':ans.answer}
329 elif ans.type in ['integer','float','date','datetime']:
330 fields[tools.ustr(que.id) + "_" + tools.ustr(ans.id) + "_multi"] = {'type': str(ans.type), 'string':ans.answer}
334 for item in ans.menu_choice.split('\n'):
335 if item and not item.strip() == '': selection.append((item ,item))
336 fields[tools.ustr(que.id) + "_" + tools.ustr(ans.id) + "_multi"] = {'type':'selection', 'selection' : selection, 'string':ans.answer}
338 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:
339 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:
340 etree.SubElement(xml_group, 'field', {'readonly' :str(readonly), 'name': tools.ustr(que.id) + "_otherfield", 'colspan':"4"})
341 fields[tools.ustr(que.id) + "_otherfield"] = {'type':'boolean', 'string':que_rec.comment_label, 'views':{}}
342 if que_rec.comment_field_type == 'char':
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': 'char', 'string': '', 'size':255, 'views':{}}
345 elif que_rec.comment_field_type == 'text':
346 etree.SubElement(xml_group, 'field', {'readonly' :str(readonly), 'name': tools.ustr(que.id) + "_other", 'nolabel':"1" ,'colspan':"4"})
347 fields[tools.ustr(que.id) + "_other"] = {'type': 'text', 'string': '', 'views':{}}
349 if que_rec.comment_field_type == 'char':
350 etree.SubElement(xml_group, 'label', {'string': to_xml(tools.ustr(que_rec.comment_label)),'colspan':"4"})
351 etree.SubElement(xml_group, 'field', {'readonly' :str(readonly), 'name': tools.ustr(que.id) + "_other", 'nolabel':"1" ,'colspan':"4"})
352 fields[tools.ustr(que.id) + "_other"] = {'type': 'char', 'string': '', 'size':255, 'views':{}}
353 elif que_rec.comment_field_type == 'text':
354 etree.SubElement(xml_group, 'label', {'string': to_xml(tools.ustr(que_rec.comment_label)),'colspan':"4"})
355 etree.SubElement(xml_group, 'field', {'readonly' :str(readonly), 'name': tools.ustr(que.id) + "_other", 'nolabel':"1" ,'colspan':"4"})
356 fields[tools.ustr(que.id) + "_other"] = {'type': 'text', 'string': '', 'views':{}}
358 etree.SubElement(xml_form, 'separator', {'colspan': '4'})
359 xml_group = etree.SubElement(xml_form, 'group', {'col': '6', 'colspan': '4'})
360 etree.SubElement(xml_group, 'field', {'name': 'progress_bar_' + tools.ustr(page_number) , 'widget':'progressbar'})
361 fields['progress_bar_' + tools.ustr(page_number)] = {'type':'float', 'string':"Progress", 'views':{}}
362 etree.SubElement(xml_group, 'label', {'string': tools.ustr(page_number+ 1) + "/" + tools.ustr(total_pages)})
363 etree.SubElement(xml_group, 'button', {'icon': "gtk-cancel", 'special': "cancel",'string':"Cancel"})
366 etree.SubElement(xml_group, 'button', {'colspan':"1",'icon':"gtk-go-back",'name':"action_previous",'string':"Previous",'type':"object"})
368 if int(page_number) + 1 == total_pages:
371 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)):
372 etree.SubElement(xml_group, 'button', {'icon': "gtk-go-forward", 'special' : 'cancel','string': tools.ustr("Done") ,'context' : tools.ustr(context)})
373 elif context.has_key('active') and context.get('active', False) and int(page_number) + 1 == total_pages and context.has_key('response_id'):
374 etree.SubElement(xml_group, 'button', {'icon': "gtk-go-forward", 'name':"action_forward_next",'string': tools.ustr("Next Answer") ,'type':"object",'context' : tools.ustr(context)})
375 elif context.has_key('active') and context.get('active',False) and int(page_number) + 1 == total_pages:
376 etree.SubElement(xml_group, 'button', {'icon': "gtk-go-forward", 'special': "cancel", 'string' : 'Done', 'context' : tools.ustr(context)})
378 etree.SubElement(xml_group, 'button', {'icon': "gtk-go-forward", 'name':"action_next",'string': tools.ustr(but_string) ,'type':"object",'context' : tools.ustr(context)})
380 if context.has_key('active') and context.get('active',False) and context.has_key('edit'):
381 etree.SubElement(xml_form, 'separator', {'string' : '','colspan': '4'})
382 context.update({'page_id' : tools.ustr(p_id),'page_number' : sur_name_rec.page_no , 'transfer' : sur_name_read.transfer})
383 xml_group3 = etree.SubElement(xml_form, 'group', {'col': '4', 'colspan': '4'})
384 etree.SubElement(xml_group3, 'button', {'string' :'Add Page','icon': "gtk-new", 'type' :'object','name':"action_new_page", 'context' : tools.ustr(context)})
385 etree.SubElement(xml_group3, 'button', {'string' :'Edit Page','icon': "gtk-edit", 'type' :'object','name':"action_edit_page", 'context' : tools.ustr(context)})
386 etree.SubElement(xml_group3, 'button', {'string' :'Delete Page','icon': "gtk-delete", 'type' :'object','name':"action_delete_page", 'context' : tools.ustr(context)})
387 etree.SubElement(xml_group3, 'button', {'string' :'Add Question','icon': "gtk-new", 'type' :'object','name':"action_new_question", 'context' : tools.ustr(context)})
389 root = xml_form.getroottree()
390 result['arch'] = etree.tostring(root)
391 result['fields'] = fields
392 result['context'] = context
394 survey_obj.write(cr, uid, survey_id, {'tot_comp_survey' : sur_rec.tot_comp_survey + 1})
395 sur_response_obj.write(cr, uid, [sur_name_read.response], {'state' : 'done'})
397 if sur_rec.send_response:
398 survey_data = survey_obj.browse(cr, uid, int(survey_id))
399 response_id = surv_name_wiz.read(cr, uid, context.get('sur_name_id',False))['response']
400 context.update({'response_id':response_id})
401 report = self.create_report(cr, uid, [int(survey_id)], 'report.survey.browse.response', survey_data.title,context)
403 file = open(tools.config['addons_path'] + '/survey/report/' + survey_data.title + ".pdf")
406 line = file.readline()
411 attachments.append((survey_data.title + ".pdf",file_data))
413 os.remove(tools.config['addons_path'] + '/survey/report/' + survey_data.title + ".pdf")
417 address_id = user_obj.browse(cr, uid, uid).address_id.id
419 cr.execute("select email from res_partner_address where id =%s", (address_id,))
420 user_email = cr.fetchone()[0]
421 resp_id = survey_data.responsible_id.address_id
424 cr.execute("select email from res_partner_address where id =%s", (resp_id.id,))
425 resp_email = cr.fetchone()[0]
426 if user_email and resp_email:
427 user_name = user_obj.browse(cr, uid, uid).name
428 mail = "Hello " + survey_data.responsible_id.name + ",\n\n " + str(user_name) + " Give Response Of " + survey_data.title + " Survey.\n\n Thanks,"
429 tools.email_send(user_email, [resp_email], "Survey Answer Of " + str(user_name) , mail, attach = attachments)
431 xml_form = etree.Element('form', {'string': _('Complete Survey Answer')})
432 etree.SubElement(xml_form, 'separator', {'string': 'Complete Survey', 'colspan': "4"})
433 etree.SubElement(xml_form, 'label', {'string': 'Thanks for your Answer'})
434 etree.SubElement(xml_form, 'newline')
435 etree.SubElement(xml_form, 'button', {'icon': "gtk-go-forward", 'special':"cancel",'string':"OK",'colspan':"2"})
436 root = xml_form.getroottree()
437 result['arch'] = etree.tostring(root)
438 result['fields'] = {}
439 result['context'] = context
442 def create_report(self, cr, uid, res_ids, report_name=False, file_name=False, context=None):
444 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.
446 @param self: The object pointer
447 @param cr: the current row, from the database cursor,
448 @param uid: the current user’s ID for security checks,
449 @param res_ids: List of survey answer IDs,
450 @param report_name: name of the report,
451 @param file_name: To give file name of the report,
452 @param context: A standard dictionary for contextual values,
453 @return : Dictionary value for created report with file nameself.
455 if not report_name or not res_ids:
456 return (False, Exception('Report name and Resources ids are required !!!'))
458 ret_file_name = tools.config['addons_path'] + '/survey/report/' + file_name + '.pdf'
459 service = netsvc.LocalService(report_name);
460 (result, format) = service.create(cr, uid, res_ids, {}, context)
461 fp = open(ret_file_name, 'wb+');
466 return (False, str(e))
468 return (True, ret_file_name)
470 def default_get(self, cr, uid, fields_list, context=None):
472 Assign Default value in particular field. If Browse Answers wizard run then read the value into database and Assigne to a particular fields.
474 @param self: The object pointer
475 @param cr: the current row, from the database cursor,
476 @param uid: the current user’s ID for security checks,
477 @param fields_list: List of fields of current view,
478 @param context: A standard dictionary for contextual values,
479 @return : Dictionary value for fields list with value.
482 for field in fields_list:
483 if field.split('_')[0] == 'progress':
484 tot_page_id = self.pool.get('survey').browse(cr, uid, context.get('survey_id',False))
485 tot_per = (float(100) * (int(field.split('_')[2]) + 1) / len(tot_page_id.page_ids))
486 value[field] = tot_per
487 response_obj = self.pool.get('survey.response')
488 surv_name_wiz = self.pool.get('survey.name.wiz')
490 if context.has_key('response_id') and context.get('response_id') and int(context['response_id'][0]) > 0:
491 data = super(survey_question_wiz, self).default_get(cr, uid, fields_list, context)
492 response_ans = response_obj.browse(cr, uid, context['response_id'][context['response_no']])
495 for que in response_ans.question_ids:
496 for field in fields_list:
497 if field.split('_')[0] != "progress" and field.split('_')[0] == str(que.question_id.id):
498 if que.response_answer_ids and len(field.split('_')) == 4 and field.split('_')[1] == "commentcolumn" and field.split('_')[3] == "field":
499 for ans in que.response_answer_ids:
500 if str(field.split('_')[2]) == str(ans.answer_id.id):
501 value[field] = ans.comment_field
503 if que.response_table_ids and len(field.split('_')) == 4 and field.split('_')[1] == "table":
504 for ans in que.response_table_ids:
505 if str(field.split('_')[2]) == str(ans.column_id.id) and str(field.split('_')[3]) == str(ans.name):
506 value[field] = ans.value
508 if que.comment and (field.split('_')[1] == "comment" or field.split('_')[1] == "other"):
509 value[field] = str(que.comment)
511 elif que.single_text and field.split('_')[1] == "single":
512 value[field] = str(que.single_text)
514 elif que.response_answer_ids and len(field.split('_')) == 3 and field.split('_')[1] == "selection":
515 for ans in que.response_answer_ids:
516 if str(field.split('_')[2]) == str( ans.answer_id.id):
517 value[field] = str(ans.column_id.id)
519 elif que.response_answer_ids and len(field.split('_')) == 2 and field.split('_')[1] == "selection":
520 value[field] = str(que.response_answer_ids[0].answer_id.id)
522 elif que.response_answer_ids and len(field.split('_')) == 3 and field.split('_')[2] != "multi" and field.split('_')[2] != "numeric":
523 for ans in que.response_answer_ids:
524 if str(field.split('_')[1]) == str( ans.answer_id.id) and str(field.split('_')[2]) == str(ans.column_id.id):
526 value[field] = ans.value_choice
531 for ans in que.response_answer_ids:
532 if str(field.split('_')[1]) == str( ans.answer_id.id):
533 value[field] = ans.answer
536 if not context.has_key('sur_name_id'):
538 if context.has_key('active') and context.get('active',False):
541 sur_name_read = surv_name_wiz.read(cr, uid, context.get('sur_name_id',False))
543 for key,val in sur_name_read['store_ans'].items():
544 for field in fields_list:
545 if field in list(val):
546 value[field] = val[field]
550 def create(self, cr, uid, vals, context=None):
552 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.
554 @param self: The object pointer
555 @param cr: the current row, from the database cursor,
556 @param uid: the current user’s ID for security checks,
558 @param context: A standard dictionary for contextual values
561 if context.has_key('active') and context.get('active',False):
564 for key,val in vals.items():
565 if key.split('_')[0] == "progress":
567 if not context.has_key('sur_name_id') and key.split('_')[0] == "wizardid":
568 context.update({'sur_name_id': int(key.split('_')[1])})
573 surv_name_wiz = self.pool.get('survey.name.wiz')
574 surv_all_resp_obj = self.pool.get('survey.response')
575 surv_tbl_column_obj = self.pool.get('survey.tbl.column.heading')
576 survey_obj = self.pool.get('survey')
577 resp_obj = self.pool.get('survey.response.line')
578 res_ans_obj = self.pool.get('survey.response.answer')
579 que_obj = self.pool.get('survey.question')
580 sur_name_read = surv_name_wiz.read(cr, uid, context.get('sur_name_id',False), [])
583 if not sur_name_read['response']:
584 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']})
585 surv_name_wiz.write(cr, uid, [context.get('sur_name_id', False)], {'response' : tools.ustr(response_id)})
587 response_id = int(sur_name_read['response'])
589 if response_id not in surv_all_resp_obj.search(cr, uid, []):
590 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)})
591 surv_name_wiz.write(cr, uid, [context.get('sur_name_id',False)], {'response' : tools.ustr(response_id)})
593 #click first time on next button then increemnet on total start suvey
594 if not sur_name_read['store_ans']:
595 his_id = self.pool.get('survey.history').create(cr, uid, {'user_id': uid, \
596 'date': strftime('%Y-%m-%d %H:%M:%S'), 'survey_id': sur_name_read['survey_id']})
597 sur_rec = survey_obj.read(cr, uid, sur_name_read['survey_id'])
598 survey_obj.write(cr, uid, sur_name_read['survey_id'], {'tot_start_survey' : sur_rec['tot_start_survey'] + 1})
599 if context.has_key('cur_id'):
600 if context.has_key('request') and context.get('request',False):
601 self.pool.get(context.get('object',False)).write(cr, uid, [int(context.get('cur_id',False))], {'response' : response_id})
602 self.pool.get(context.get('object',False)).survey_req_done(cr, uid, [int(context.get('cur_id'))], context)
604 self.pool.get(context.get('object',False)).write(cr, uid, [int(context.get('cur_id',False))], {'response' : response_id})
605 if sur_name_read['store_ans'] and type(sur_name_read['store_ans']) == dict:
606 for key,val in sur_name_read['store_ans'].items():
608 if field.split('_')[0] == val['question_id']:
610 click_update.append(key)
613 sur_name_read['store_ans'] = {}
617 for key, val in vals.items():
618 que_id = key.split('_')[0]
619 if que_id not in que_li:
620 que_li.append(que_id)
621 que_rec = que_obj.read(cr, uid, [int(que_id)], [])[0]
623 'question_id': que_id,
624 'date_create': datetime.datetime.now(),
626 'response_id': response_id
628 resp_id = resp_obj.create(cr, uid, res_data)
629 resp_id_list.append(resp_id)
630 sur_name_read['store_ans'].update({resp_id:{'question_id':que_id}})
631 surv_name_wiz.write(cr, uid, [context.get('sur_name_id',False)], {'store_ans':sur_name_read['store_ans']})
636 comment_field = False
637 comment_value = False
640 for key1, val1 in vals.items():
641 if val1 and key1.split('_')[1] == "table" and key1.split('_')[0] == que_id:
642 surv_tbl_column_obj.create(cr, uid, {'response_table_id' : resp_id,'column_id':key1.split('_')[2], 'name':key1.split('_')[3], 'value' : val1})
643 sur_name_read['store_ans'][resp_id].update({key1:val1})
646 elif val1 and key1.split('_')[1] == "otherfield" and key1.split('_')[0] == que_id:
648 sur_name_read['store_ans'][resp_id].update({key1:val1})
650 surv_name_wiz.write(cr, uid, [context.get('sur_name_id',False)], {'store_ans':sur_name_read['store_ans']})
653 elif val1 and key1.split('_')[1] == "selection" and key1.split('_')[0] == que_id:
654 if len(key1.split('_')) > 2:
655 ans_create_id = res_ans_obj.create(cr, uid, {'response_id':resp_id, 'answer_id':key1.split('_')[-1], 'column_id' : val1})
656 selected_value.append(val1)
657 response_list.append(str(ans_create_id) + "_" + str(key1.split('_')[-1]))
659 ans_create_id = res_ans_obj.create(cr, uid, {'response_id':resp_id, 'answer_id':val1})
660 sur_name_read['store_ans'][resp_id].update({key1:val1})
663 elif key1.split('_')[1] == "other" and key1.split('_')[0] == que_id:
668 if que_rec['is_comment_require'] and que_rec['comment_valid_type'] == 'must_be_specific_length':
669 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']:
671 elif que_rec['is_comment_require'] and que_rec['comment_valid_type'] in ['must_be_whole_number', 'must_be_decimal_number', 'must_be_date']:
674 if que_rec['comment_valid_type'] == 'must_be_whole_number':
676 if value < que_rec['comment_minimum_no'] or value > que_rec['comment_maximum_no']:
678 elif que_rec['comment_valid_type'] == 'must_be_decimal_number':
680 if value < que_rec['comment_minimum_float'] or value > que_rec['comment_maximum_float']:
682 elif que_rec['comment_valid_type'] == 'must_be_date':
683 value = datetime.datetime.strptime(val1, "%Y-%m-%d")
684 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"):
688 elif que_rec['is_comment_require'] and que_rec['comment_valid_type'] == 'must_be_email_address':
690 if re.match("^[a-zA-Z0-9._%-+]+@[a-zA-Z0-9._%-]+.[a-zA-Z]{2,6}$", val1) == None:
693 for res in resp_id_list:
694 sur_name_read['store_ans'].pop(res)
695 raise osv.except_osv(_('Warning !'), _("'" + que_rec['question'] + "' \n" + tools.ustr(que_rec['comment_valid_err_msg'])))
697 resp_obj.write(cr, uid, resp_id, {'comment':val1})
698 sur_name_read['store_ans'][resp_id].update({key1:val1})
700 elif val1 and key1.split('_')[1] == "comment" and key1.split('_')[0] == que_id:
701 resp_obj.write(cr, uid, resp_id, {'comment':val1})
702 sur_name_read['store_ans'][resp_id].update({key1:val1})
705 elif val1 and key1.split('_')[0] == que_id and (key1.split('_')[1] == "single" or (len(key1.split('_')) > 2 and key1.split('_')[2] == 'multi')):
707 if que_rec['is_validation_require'] and que_rec['validation_type'] == 'must_be_specific_length':
708 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']:
710 elif que_rec['is_validation_require'] and que_rec['validation_type'] in ['must_be_whole_number', 'must_be_decimal_number', 'must_be_date']:
713 if que_rec['validation_type'] == 'must_be_whole_number':
715 if value < que_rec['validation_minimum_no'] or value > que_rec['validation_maximum_no']:
717 elif que_rec['validation_type'] == 'must_be_decimal_number':
719 if value < que_rec['validation_minimum_float'] or value > que_rec['validation_maximum_float']:
721 elif que_rec['validation_type'] == 'must_be_date':
722 value = datetime.datetime.strptime(val1, "%Y-%m-%d")
723 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"):
727 elif que_rec['is_validation_require'] and que_rec['validation_type'] == 'must_be_email_address':
729 if re.match("^[a-zA-Z0-9._%-+]+@[a-zA-Z0-9._%-]+.[a-zA-Z]{2,6}$", val1) == None:
732 for res in resp_id_list:
733 sur_name_read['store_ans'].pop(res)
734 raise osv.except_osv(_('Warning !'), _("'" + que_rec['question'] + "' \n" + tools.ustr(que_rec['validation_valid_err_msg'])))
736 if key1.split('_')[1] == "single" :
737 resp_obj.write(cr, uid, resp_id, {'single_text':val1})
739 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})
744 elif val1 and que_id == key1.split('_')[0] and len(key1.split('_')) > 2 and key1.split('_')[2] == 'numeric':
747 numeric_sum += int(val1)
748 ans_create_id = res_ans_obj.create(cr, uid, {'response_id':resp_id, 'answer_id':key1.split('_')[1], 'answer' : val1})
749 sur_name_read['store_ans'][resp_id].update({key1:val1})
752 for res in resp_id_list:
753 sur_name_read['store_ans'].pop(res)
754 raise osv.except_osv(_('Warning !'), _("'" + que_rec['question'] + "' \nPlease enter an integer value " ))
756 elif val1 and que_id == key1.split('_')[0] and len(key1.split('_')) == 3:
757 if type(val1) == type('') or type(val1) == type(u''):
758 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})
759 sur_name_read['store_ans'][resp_id].update({key1:val1})
761 ans_create_id = res_ans_obj.create(cr, uid, {'response_id':resp_id, 'answer_id':key1.split('_')[1], 'column_id' : key1.split('_')[2]})
762 sur_name_read['store_ans'][resp_id].update({key1:True})
764 matrix_list.append(key1.split('_')[0] + '_' + key1.split('_')[1])
767 elif val1 and que_id == key1.split('_')[0] and len(key1.split('_')) == 2:
768 ans_create_id = res_ans_obj.create(cr, uid, {'response_id':resp_id, 'answer_id':key1.split('_')[-1], 'answer' : val1})
769 sur_name_read['store_ans'][resp_id].update({key1:val1})
771 surv_name_wiz.write(cr, uid, [context.get('sur_name_id',False)], {'store_ans':sur_name_read['store_ans']})
773 for key,val in vals.items():
774 if val and key.split('_')[1] == "commentcolumn" and key.split('_')[0] == que_id:
775 for res_id in response_list:
776 if key.split('_')[2] in res_id.split('_')[1]:
777 a = res_ans_obj.write(cr, uid, [res_id.split('_')[0]], {'comment_field':val})
778 sur_name_read['store_ans'][resp_id].update({key:val})
780 if comment_field and comment_value:
781 for res in resp_id_list:
782 sur_name_read['store_ans'].pop(res)
783 raise osv.except_osv(_('Warning !'), _("'" + que_rec['question'] + "' " + tools.ustr(que_rec['make_comment_field_err_msg'])))
785 if que_rec['type'] == "rating_scale" and que_rec['rating_allow_one_column_require'] and len(selected_value) > len(list(set(selected_value))):
786 for res in resp_id_list:
787 sur_name_read['store_ans'].pop(res)
788 raise osv.except_osv(_('Warning !'), _("'" + que_rec['question'] + "\n you cannot select same answer more than one times'"))
791 resp_obj.write(cr, uid, resp_id, {'state':'skip'})
793 if que_rec['numeric_required_sum'] and numeric_sum > que_rec['numeric_required_sum']:
794 for res in resp_id_list:
795 sur_name_read['store_ans'].pop(res)
796 raise osv.except_osv(_('Warning !'), _("'" + que_rec['question'] + "' " + tools.ustr(que_rec['numeric_required_sum_err_msg'])))
798 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']:
800 if (que_rec['required_type'] == 'all' and len(list(set(matrix_list))) < len(que_rec['answer_choice_ids'])) or \
801 (que_rec['required_type'] == 'at least' and len(list(set(matrix_list))) < que_rec['req_ans']) or \
802 (que_rec['required_type'] == 'at most' and len(list(set(matrix_list))) > que_rec['req_ans']) or \
803 (que_rec['required_type'] == 'exactly' and len(list(set(matrix_list))) != que_rec['req_ans']) or \
804 (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'])):
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 elif (que_rec['required_type'] == 'all' and select_count < len(que_rec['answer_choice_ids'])) or \
810 (que_rec['required_type'] == 'at least' and select_count < que_rec['req_ans']) or \
811 (que_rec['required_type'] == 'at most' and select_count > que_rec['req_ans']) or \
812 (que_rec['required_type'] == 'exactly' and select_count != que_rec['req_ans']) or \
813 (que_rec['required_type'] == 'a range' and (select_count < que_rec['minimum_req_ans'] or select_count > que_rec['maximum_req_ans'])):
814 for res in resp_id_list:
815 sur_name_read['store_ans'].pop(res)
816 raise osv.except_osv(_('Warning !'), _("'" + que_rec['question'] + "' " + tools.ustr(que_rec['req_error_msg'])))
818 if que_rec['type'] in ['multiple_choice_only_one_ans','single_textbox','comment'] and que_rec['is_require_answer'] and select_count <= 0:
819 for res in resp_id_list:
820 sur_name_read['store_ans'].pop(res)
821 raise osv.except_osv(_('Warning !'), _("'" + que_rec['question'] + "' " + tools.ustr(que_rec['req_error_msg'])))
825 for update in click_update:
826 que_rec = que_obj.read(cr, uid , [int(sur_name_read['store_ans'][update]['question_id'])], [])[0]
827 res_ans_obj.unlink(cr, uid,res_ans_obj.search(cr, uid, [('response_id', '=', update)]))
828 surv_tbl_column_obj.unlink(cr, uid,surv_tbl_column_obj.search(cr, uid, [('response_table_id', '=', update)]))
829 resp_id_list.append(update)
830 sur_name_read['store_ans'].update({update:{'question_id':sur_name_read['store_ans'][update]['question_id']}})
831 surv_name_wiz.write(cr, uid, [context.get('sur_name_id',False)], {'store_ans':sur_name_read['store_ans']})
836 comment_field = False
837 comment_value = False
840 for key, val in vals.items():
841 ans_id_len = key.split('_')
842 if ans_id_len[0] == sur_name_read['store_ans'][update]['question_id']:
843 if val and key.split('_')[1] == "table":
844 surv_tbl_column_obj.create(cr, uid, {'response_table_id' : update,'column_id':key.split('_')[2], 'name':key.split('_')[3], 'value' : val})
845 sur_name_read['store_ans'][update].update({key:val})
846 resp_obj.write(cr, uid, update, {'state': 'done'})
848 elif val and key.split('_')[1] == "otherfield" :
850 sur_name_read['store_ans'][update].update({key:val})
852 surv_name_wiz.write(cr, uid, [context.get('sur_name_id',False)], {'store_ans':sur_name_read['store_ans']})
855 elif val and key.split('_')[1] == "selection":
856 if len(key.split('_')) > 2:
857 ans_create_id = res_ans_obj.create(cr, uid, {'response_id':update, 'answer_id':key.split('_')[-1], 'column_id' : val})
858 selected_value.append(val)
859 response_list.append(str(ans_create_id) + "_" + str(key.split('_')[-1]))
861 ans_create_id = res_ans_obj.create(cr, uid, {'response_id':update, 'answer_id': val})
862 resp_obj.write(cr, uid, update, {'state': 'done'})
863 sur_name_read['store_ans'][update].update({key:val})
866 elif key.split('_')[1] == "other":
871 if que_rec['is_comment_require'] and que_rec['comment_valid_type'] == 'must_be_specific_length':
872 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']:
874 elif que_rec['is_comment_require'] and que_rec['comment_valid_type'] in ['must_be_whole_number', 'must_be_decimal_number', 'must_be_date']:
876 if que_rec['comment_valid_type'] == 'must_be_whole_number':
878 if value < que_rec['comment_minimum_no'] or value > que_rec['comment_maximum_no']:
880 elif que_rec['comment_valid_type'] == 'must_be_decimal_number':
882 if value < que_rec['comment_minimum_float'] or value > que_rec['comment_maximum_float']:
884 elif que_rec['comment_valid_type'] == 'must_be_date':
885 value = datetime.datetime.strptime(val, "%Y-%m-%d")
886 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"):
890 elif que_rec['is_comment_require'] and que_rec['comment_valid_type'] == 'must_be_email_address':
892 if re.match("^[a-zA-Z0-9._%-+]+@[a-zA-Z0-9._%-]+.[a-zA-Z]{2,6}$", val) == None:
895 raise osv.except_osv(_('Warning !'), _("'" + que_rec['question'] + "' \n" + tools.ustr(que_rec['comment_valid_err_msg'])))
896 resp_obj.write(cr, uid, update, {'comment':val,'state': 'done'})
897 sur_name_read['store_ans'][update].update({key:val})
899 elif val and key.split('_')[1] == "comment":
900 resp_obj.write(cr, uid, update, {'comment':val,'state': 'done'})
901 sur_name_read['store_ans'][update].update({key:val})
904 elif val and (key.split('_')[1] == "single" or (len(key.split('_')) > 2 and key.split('_')[2] == 'multi')):
906 if que_rec['is_validation_require'] and que_rec['validation_type'] == 'must_be_specific_length':
907 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']:
909 elif que_rec['is_validation_require'] and que_rec['validation_type'] in ['must_be_whole_number', 'must_be_decimal_number', 'must_be_date']:
912 if que_rec['validation_type'] == 'must_be_whole_number':
914 if value < que_rec['validation_minimum_no'] or value > que_rec['validation_maximum_no']:
916 elif que_rec['validation_type'] == 'must_be_decimal_number':
918 if value < que_rec['validation_minimum_float'] or value > que_rec['validation_maximum_float']:
920 elif que_rec['validation_type'] == 'must_be_date':
921 value = datetime.datetime.strptime(val, "%Y-%m-%d")
922 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"):
926 elif que_rec['is_validation_require'] and que_rec['validation_type'] == 'must_be_email_address':
928 if re.match("^[a-zA-Z0-9._%-+]+@[a-zA-Z0-9._%-]+.[a-zA-Z]{2,6}$", val) == None:
931 raise osv.except_osv(_('Warning !'), _("'" + que_rec['question'] + "' \n" + tools.ustr(que_rec['validation_valid_err_msg'])))
932 if key.split('_')[1] == "single" :
933 resp_obj.write(cr, uid, update, {'single_text':val,'state': 'done'})
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 elif val and len(key.split('_')) > 2 and key.split('_')[2] == 'numeric':
943 numeric_sum += int(val)
944 resp_obj.write(cr, uid, update, {'state': 'done'})
945 ans_create_id = res_ans_obj.create(cr, uid, {'response_id': update, 'answer_id':ans_id_len[1], 'answer' : val})
946 sur_name_read['store_ans'][update].update({key:val})
949 raise osv.except_osv(_('Warning !'), _("'" + que_rec['question'] + "' \n Please enter an integer value " ))
951 elif val and len(key.split('_')) == 3:
952 resp_obj.write(cr, uid, update, {'state': 'done'})
953 if type(val) == type('') or type(val) == type(u''):
954 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})
955 sur_name_read['store_ans'][update].update({key:val})
957 ans_create_id = res_ans_obj.create(cr, uid, {'response_id': update, 'answer_id':ans_id_len[1], 'column_id' : ans_id_len[2]})
958 sur_name_read['store_ans'][update].update({key:True})
959 matrix_list.append(key.split('_')[0] + '_' + key.split('_')[1])
962 elif val and len(key.split('_')) == 2:
963 resp_obj.write(cr, uid, update, {'state': 'done'})
964 ans_create_id = res_ans_obj.create(cr, uid, {'response_id': update, 'answer_id':ans_id_len[-1], 'answer' : val})
965 sur_name_read['store_ans'][update].update({key:val})
967 surv_name_wiz.write(cr, uid, [context.get('sur_name_id',False)], {'store_ans': sur_name_read['store_ans']})
969 for key,val in vals.items():
970 if val and key.split('_')[1] == "commentcolumn" and key.split('_')[0] == sur_name_read['store_ans'][update]['question_id']:
971 for res_id in response_list:
972 if key.split('_')[2] in res_id.split('_')[1]:
973 a = res_ans_obj.write(cr, uid, [res_id.split('_')[0]], {'comment_field':val})
974 sur_name_read['store_ans'][update].update({key:val})
976 if comment_field and comment_value:
977 raise osv.except_osv(_('Warning !'), _("'" + que_rec['question'] + "' " + tools.ustr(que_rec['make_comment_field_err_msg'])))
979 if que_rec['type'] == "rating_scale" and que_rec['rating_allow_one_column_require'] and len(selected_value) > len(list(set(selected_value))):
980 raise osv.except_osv(_('Warning !'), _("'" + que_rec['question'] + "\n you cannot select same answer more than one times'"))
982 if que_rec['numeric_required_sum'] and numeric_sum > que_rec['numeric_required_sum']:
983 raise osv.except_osv(_('Warning !'), _("'" + que_rec['question'] + "' " + tools.ustr(que_rec['numeric_required_sum_err_msg'])))
986 resp_obj.write(cr, uid, update, {'state': 'skip'})
988 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']:
990 if (que_rec['required_type'] == 'all' and len(list(set(matrix_list))) < len(que_rec['answer_choice_ids'])) or \
991 (que_rec['required_type'] == 'at least' and len(list(set(matrix_list))) < que_rec['req_ans']) or \
992 (que_rec['required_type'] == 'at most' and len(list(set(matrix_list))) > que_rec['req_ans']) or \
993 (que_rec['required_type'] == 'exactly' and len(list(set(matrix_list))) != que_rec['req_ans']) or \
994 (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'])):
995 raise osv.except_osv(_('Warning !'), _("'" + que_rec['question'] + "' " + tools.ustr(que_rec['req_error_msg'])))
997 elif (que_rec['required_type'] == 'all' and select_count < len(que_rec['answer_choice_ids'])) or \
998 (que_rec['required_type'] == 'at least' and select_count < que_rec['req_ans']) or \
999 (que_rec['required_type'] == 'at most' and select_count > que_rec['req_ans']) or \
1000 (que_rec['required_type'] == 'exactly' and select_count != que_rec['req_ans']) or \
1001 (que_rec['required_type'] == 'a range' and (select_count < que_rec['minimum_req_ans'] or select_count > que_rec['maximum_req_ans'])):
1002 raise osv.except_osv(_('Warning !'), _("'" + que_rec['question'] + "' " + tools.ustr(que_rec['req_error_msg'])))
1004 if que_rec['type'] in ['multiple_choice_only_one_ans','single_textbox','comment'] and que_rec['is_require_answer'] and select_count <= 0:
1005 raise osv.except_osv(_('Warning !'), _("'" + que_rec['question'] + "' " + tools.ustr(que_rec['req_error_msg'])))
1009 def action_new_question(self,cr, uid, ids, context):
1011 New survey.Question form.
1013 @param self: The object pointer
1014 @param cr: the current row, from the database cursor,
1015 @param uid: the current user’s ID for security checks,
1016 @param ids: List of survey.question.wiz IDs
1017 @param context: A standard dictionary for contextual values
1018 @return : Dictionary value for Open new survey.Qestion form.
1020 for key,val in context.items():
1021 if type(key) == type(True):
1023 view_id = self.pool.get('ir.ui.view').search(cr,uid,[('model','=','survey.question'),\
1024 ('name','=','survey_question_wizard_test')])
1026 'view_type': 'form',
1027 "view_mode": 'form',
1028 'res_model': 'survey.question',
1029 'type': 'ir.actions.act_window',
1035 def action_new_page(self, cr, uid, ids, context):
1037 New survey.Page form.
1039 @param self: The object pointer
1040 @param cr: the current row, from the database cursor,
1041 @param uid: the current user’s ID for security checks,
1042 @param ids: List of survey.question.wiz IDs
1043 @param context: A standard dictionary for contextual values
1044 @return : Dictionary value for Open new survey.page form.
1046 for key,val in context.items():
1047 if type(key) == type(True):
1049 view_id = self.pool.get('ir.ui.view').search(cr,uid,[('model','=','survey.page'),\
1050 ('name','=','survey_page_wizard_test')])
1052 'view_type': 'form',
1053 "view_mode": 'form',
1054 'res_model': 'survey.page',
1055 'type': 'ir.actions.act_window',
1061 def action_edit_page(self,cr, uid, ids, context):
1065 @param self: The object pointer
1066 @param cr: the current row, from the database cursor,
1067 @param uid: the current user’s ID for security checks,
1068 @param ids: List of survey.question.wiz IDs
1069 @param context: A standard dictionary for contextual values
1070 @return : Dictionary value for Open Edit survey.page form.
1072 for key,val in context.items():
1073 if type(key) == type(True):
1075 view_id = self.pool.get('ir.ui.view').search(cr,uid,[('model','=','survey.page'),\
1076 ('name','=','survey_page_wizard_test')])
1078 'view_type': 'form',
1079 "view_mode": 'form',
1080 'res_model': 'survey.page',
1081 'type': 'ir.actions.act_window',
1083 'res_id': int(context.get('page_id',0)),
1088 def action_delete_page(self,cr, uid, ids, context):
1092 @param self: The object pointer
1093 @param cr: the current row, from the database cursor,
1094 @param uid: the current user’s ID for security checks,
1095 @param ids: List of survey.question.wiz IDs
1096 @param context: A standard dictionary for contextual values
1097 @return : Dictionary value for Open next survey.page form, but delete the selected page.
1099 for key,val in context.items():
1100 if type(key) == type(True):
1103 self.pool.get('survey.page').unlink(cr, uid, [context.get('page_id',False)])
1104 search_id = self.pool.get('ir.ui.view').search(cr,uid,[('model','=','survey.question.wiz'),\
1105 ('name','=','Survey Search')])
1106 surv_name_wiz = self.pool.get('survey.name.wiz')
1107 surv_name_wiz.write(cr, uid, [context.get('sur_name_id',False)], \
1108 {'transfer':True, 'page_no' : context.get('page_number',False) })
1110 'view_type': 'form',
1111 "view_mode": 'form',
1112 'res_model': 'survey.question.wiz',
1113 'type': 'ir.actions.act_window',
1115 'search_view_id':search_id[0],
1119 def action_edit_question(self,cr, uid, ids, context):
1121 Edit survey.question.
1123 @param self: The object pointer
1124 @param cr: the current row, from the database cursor,
1125 @param uid: the current user’s ID for security checks,
1126 @param ids: List of survey.question.wiz IDs
1127 @param context: A standard dictionary for contextual values
1128 @return : Dictionary value for Open Edit survey.question form.
1130 for key,val in context.items():
1131 if type(key) == type(True):
1133 view_id = self.pool.get('ir.ui.view').search(cr,uid,[('model','=','survey.question'),\
1134 ('name','=','survey_question_wizard_test')])
1136 'view_type': 'form',
1137 "view_mode": 'form',
1138 'res_model': 'survey.question',
1139 'type': 'ir.actions.act_window',
1141 'res_id' : int(context.get('question_id',0)),
1146 def action_delete_question(self,cr, uid, ids, context):
1148 Delete survey.question.
1150 @param self: The object pointer
1151 @param cr: the current row, from the database cursor,
1152 @param uid: the current user’s ID for security checks,
1153 @param ids: List of survey.question.wiz IDs
1154 @param context: A standard dictionary for contextual values
1155 @return : Dictionary value for Open same survey.page form, but delete the selected survey.question in current survey.page.
1157 for key,val in context.items():
1158 if type(key) == type(True):
1161 que_obj = self.pool.get('survey.question')
1162 que_obj.unlink(cr, uid, [context.get('question_id',False)])
1163 search_id = self.pool.get('ir.ui.view').search(cr,uid,[('model','=','survey.question.wiz'),\
1164 ('name','=','Survey Search')])
1165 surv_name_wiz = self.pool.get('survey.name.wiz')
1166 surv_name_wiz.write(cr, uid, [context.get('sur_name_id',False)],\
1167 {'transfer':True, 'page_no' : context.get('page_number',0) })
1169 'view_type': 'form',
1170 "view_mode": 'form',
1171 'res_model': 'survey.question.wiz',
1172 'type': 'ir.actions.act_window',
1174 'search_view_id': search_id[0],
1178 def action_forward_previous(self, cr, uid, ids, context=None):
1180 Goes to previous Survey Answer.
1182 @param self: The object pointer
1183 @param cr: the current row, from the database cursor,
1184 @param uid: the current user’s ID for security checks,
1185 @param ids: List of survey.question.wiz IDs
1186 @param context: A standard dictionary for contextual values
1187 @return : Dictionary value for Open Previous Answer form.
1189 search_obj = self.pool.get('ir.ui.view')
1190 surv_name_wiz = self.pool.get('survey.name.wiz')
1191 search_id = search_obj.search(cr,uid,[('model','=','survey.question.wiz'),\
1192 ('name','=','Survey Search')])
1193 wiz_id = surv_name_wiz.create(cr,uid, {'survey_id': context.get('survey_id',False),'page_no' :-1,'page':'next','transfer' :1,'response':0})
1194 context.update({'sur_name_id' :wiz_id, 'response_no': context.get('response_no',0) - 1})
1196 if context.get('response_no',0) + 1 > len(context.get('response_id',0)):
1199 'view_type': 'form',
1200 "view_mode": 'form',
1201 'res_model': 'survey.question.wiz',
1202 'type': 'ir.actions.act_window',
1204 'search_view_id': search_id[0],
1208 def action_forward_next(self, cr, uid, ids, context=None):
1210 Goes to Next Survey Answer.
1212 @param self: The object pointer
1213 @param cr: the current row, from the database cursor,
1214 @param uid: the current user’s ID for security checks,
1215 @param ids: List of survey.question.wiz IDs
1216 @param context: A standard dictionary for contextual values
1217 @return : Dictionary value for Open Next Answer form.
1219 search_obj = self.pool.get('ir.ui.view')
1220 surv_name_wiz = self.pool.get('survey.name.wiz')
1221 search_id = search_obj.search(cr,uid,[('model','=','survey.question.wiz'),\
1222 ('name','=','Survey Search')])
1223 wiz_id = surv_name_wiz.create(cr,uid, {'survey_id' : context.get('survey_id',False),'page_no' :-1,'page':'next','transfer' :1,'response':0})
1224 context.update({'sur_name_id' :wiz_id, 'response_no' : context.get('response_no',0) + 1})
1226 if context.get('response_no',0) + 1 > len(context.get('response_id',0)):
1229 'view_type': 'form',
1230 "view_mode": 'form',
1231 'res_model': 'survey.question.wiz',
1232 'type': 'ir.actions.act_window',
1234 'search_view_id': search_id[0],
1238 def action_next(self, cr, uid, ids, context=None):
1242 @param self: The object pointer
1243 @param cr: the current row, from the database cursor,
1244 @param uid: the current user’s ID for security checks,
1245 @param ids: List of survey.question.wiz IDs
1246 @param context: A standard dictionary for contextual values
1247 @return : Dictionary value for Open Next survey.page form.
1249 surv_name_wiz = self.pool.get('survey.name.wiz')
1250 search_obj = self.pool.get('ir.ui.view')
1251 search_id = search_obj.search(cr,uid,[('model','=','survey.question.wiz'),('name','=','Survey Search')])
1252 surv_name_wiz.write(cr, uid, [context.get('sur_name_id',False)], {'transfer':True, 'page':'next'})
1254 'view_type': 'form',
1255 "view_mode": 'form',
1256 'res_model': 'survey.question.wiz',
1257 'type': 'ir.actions.act_window',
1259 'search_view_id': search_id[0],
1263 def action_previous(self, cr, uid, ids, context=None):
1265 Goes to previous page.
1267 @param self: The object pointer
1268 @param cr: the current row, from the database cursor,
1269 @param uid: the current user’s ID for security checks,
1270 @param ids: List of survey.question.wiz IDs
1271 @param context: A standard dictionary for contextual values
1272 @return : Dictionary value for Open Previous survey.page form.
1274 surv_name_wiz = self.pool.get('survey.name.wiz')
1275 search_obj = self.pool.get('ir.ui.view')
1276 search_id = search_obj.search(cr,uid,[('model','=','survey.question.wiz'),\
1277 ('name','=','Survey Search')])
1278 surv_name_wiz.write(cr, uid, [context.get('sur_name_id',False)], {'transfer':True, 'page':'previous'})
1280 'view_type': 'form',
1281 "view_mode": 'form',
1282 'res_model': 'survey.question.wiz',
1283 'type': 'ir.actions.act_window',
1285 'search_view_id': search_id[0],
1289 survey_question_wiz()
1291 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: