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 ##############################################################################
23 from osv import fields, osv
25 from time import strftime
28 from tools.translate import _
29 from lxml import etree
30 from tools import to_xml
33 class survey(osv.osv):
35 _description = 'Survey'
38 'title' : fields.char('Survey Title', size=128, required=1),
39 'page_ids' : fields.one2many('survey.page', 'survey_id', 'Page'),
40 'date_open' : fields.datetime('Survey Open Date', readonly=1),
41 'date_close' : fields.datetime('Survey Close Date', readonly=1),
42 'max_response_limit' : fields.integer('Maximum Response Limit'),
43 'response_user' : fields.integer('Maximum Response per User',
44 help="Set to one if you require only one response per user"),
45 'state' : fields.selection([('draft', 'Draft'), ('open', 'Open'), ('close', 'Closed'), ('cancel', 'Cancelled')], 'Status', readonly=True),
46 'responsible_id' : fields.many2one('res.users', 'Responsible'),
47 'tot_start_survey' : fields.integer("Total Started Survey", readonly=1),
48 'tot_comp_survey' : fields.integer("Total Completed Survey", readonly=1),
49 'note' : fields.text('Description', size=128),
50 'history' : fields.one2many('survey.history', 'survey_id', 'History Lines', readonly=True),
51 'users': fields.many2many('res.users', 'survey_users_rel', 'sid', 'uid', 'Users'),
52 'question_prefix' : fields.char('Question Prefix', size=128, required=1),
55 'state' : lambda * a: "draft",
56 'tot_start_survey' : lambda * a: 0,
57 'tot_comp_survey' : lambda * a: 0,
58 'question_prefix' : lambda * a: "Que ",
61 def survey_draft(self, cr, uid, ids, arg):
62 self.write(cr, uid, ids, { 'state' : 'draft'})
65 def survey_open(self, cr, uid, ids, arg):
66 self.write(cr, uid, ids, { 'state' : 'open', 'date_open':strftime("%Y-%m-%d %H:%M:%S")})
69 def survey_close(self, cr, uid, ids, arg):
70 self.write(cr, uid, ids, { 'state' : 'close', 'date_close':strftime("%Y-%m-%d %H:%M:%S") })
73 def survey_cancel(self, cr, uid, ids, arg):
74 self.write(cr, uid, ids, { 'state' : 'cancel' })
79 class survey_history(osv.osv):
80 _name = 'survey.history'
81 _description = 'Survey History'
84 'survey_id' : fields.many2one('survey', 'Survey'),
85 'user_id' : fields.many2one('res.users', 'User', readonly=True),
86 'date' : fields.datetime('Date started', readonly=1),
89 'date' : lambda * a: datetime.datetime.now()
94 class survey_page(osv.osv):
96 _description = 'Survey Pages'
100 'title' : fields.char('Page Title', size=128, required=1),
101 'survey_id' : fields.many2one('survey', 'Survey', ondelete='cascade'),
102 'question_ids' : fields.one2many('survey.question', 'page_id', 'Question'),
103 'sequence' : fields.integer('Page Nr'),
104 'note' : fields.text('Description'),
107 'sequence' : lambda * a: 1
109 def default_get(self, cr, uid, fields, context={}):
110 data = super(survey_page, self).default_get(cr, uid, fields, context)
111 if context.has_key('line_order') and context['line_order']:
112 if len(context['line_order'][-1]) > 2 and context['line_order'][-1][2].has_key('sequence'):
113 data['sequence'] = context['line_order'][-1][2]['sequence'] + 1
117 class survey_question(osv.osv):
118 _name = 'survey.question'
119 _description = 'Survey Question'
120 _rec_name = 'question'
123 def _calc_response(self, cr, uid, ids, field_name, arg, context):
125 cr.execute("select question_id, count(id) as Total_response from survey_response_line where state='done' and question_id in (%s) group by question_id" % ",".join(map(str, map(int, ids))))
126 ids1 = copy.deepcopy(ids)
127 for rec in cr.fetchall():
129 val[rec[0]] = int(rec[1])
135 'page_id' : fields.many2one('survey.page', 'Survey Page', ondelete='cascade', required=1),
136 'question' : fields.char('Question', size=128, required=1),
137 'answer_choice_ids' : fields.one2many('survey.answer', 'question_id', 'Answer'),
138 'response_ids' : fields.one2many('survey.response.line', 'question_id', 'Response', readonly=1),
139 'is_require_answer' : fields.boolean('Required Answer'),
140 'required_type' : fields.selection([('',''), ('all','All'), ('at least','At Least'), ('at most','At Most'), ('exactly','Exactly'), ('a range','A Range')], 'Respondent must answer'),
141 'req_ans' : fields.integer('#Required Answer'),
142 'maximum_req_ans' : fields.integer('Maximum Required Answer'),
143 'minimum_req_ans' : fields.integer('Minimum Required Answer'),
144 'req_error_msg' : fields.text('Error Message'),
145 'allow_comment' : fields.boolean('Allow Comment Field'),
146 'sequence' : fields.integer('Sequence'),
147 'tot_resp' : fields.function(_calc_response, method=True, string="Total Response"),
148 'survey' : fields.related('page_id', 'survey_id', type='many2one', relation='survey', string='Survey'),
149 'descriptive_text' : fields.text('Descriptive Text', size=255),
150 'column_heading_ids' : fields.one2many('survey.question.column.heading', 'question_id',' Column heading'),
151 'column_ids' : fields.one2many('survey.tbl.column.heading', 'question_id',' Column'),
152 'type' : fields.selection([('multiple_choice_only_one_ans','Multiple Choice (Only One Answer)'),
153 ('multiple_choice_multiple_ans','Multiple Choice (Multiple Answer)'),
154 ('matrix_of_choices_only_one_ans','Matrix of Choices (Only One Answers Per Row)'),
155 ('matrix_of_choices_only_multi_ans','Matrix of Choices (Multiple Answers Per Row)'),
156 ('matrix_of_drop_down_menus','Matrix of Drop-down Menus'),
157 ('rating_scale','Rating Scale'),('single_textbox','Single Textbox'),
158 ('multiple_textboxes','Multiple Textboxes'),('comment','Comment/Essay Box'),
159 ('numerical_textboxes','Numerical Textboxes'),('date','Date'),
160 ('date_and_time','Date and Time'),('descriptive_text','Descriptive Text'),
162 ], 'Question Type', required=1,),
163 'comment_label' : fields.char('Field Label', size = 255),
164 'comment_field_type' : fields.selection([('',''),('char', 'Single Line Of Text'), ('text', 'Paragraph of Text')], 'Comment Field Type'),
165 'comment_valid_type' : fields.selection([('do_not_validate', '''Don't Validate Comment Text.'''),
166 ('must_be_specific_length', 'Must Be Specific Length'),
167 ('must_be_whole_number', 'Must Be A Whole Number'),
168 ('must_be_decimal_number', 'Must Be A Decimal Number'),
169 ('must_be_date', 'Must Be A Date'),
170 ('must_be_email_address', 'Must Be An Email Address'),
171 ], 'Text Validation'),
172 'comment_minimum_no' : fields.integer('Minimum number'),
173 'comment_maximum_no' : fields.integer('Maximum number'),
174 'comment_minimum_float' : fields.float('Minimum decimal number'),
175 'comment_maximum_float' : fields.float('Maximum decimal number'),
176 'comment_minimum_date' : fields.date('Minimum date'),
177 'comment_maximum_date' : fields.date('Maximum date'),
178 'comment_valid_err_msg' : fields.text('Error message'),
179 'make_comment_field' : fields.boolean('Make Comment Field an Answer Choice'),
180 'make_comment_field_err_msg' : fields.text('Error message'),
181 'validation_type' : fields.selection([('do_not_validate', '''Don't Validate Comment Text.'''),\
182 ('must_be_specific_length', 'Must Be Specific Length'),\
183 ('must_be_whole_number', 'Must Be A Whole Number'),\
184 ('must_be_decimal_number', 'Must Be A Decimal Number'),\
185 ('must_be_date', 'Must Be A Date'),\
186 ('must_be_email_address', 'Must Be An Email Address')\
187 ], 'Text Validation'),
188 'validation_minimum_no' : fields.integer('Minimum number'),
189 'validation_maximum_no' : fields.integer('Maximum number'),
190 'validation_minimum_float' : fields.float('Minimum decimal number'),
191 'validation_maximum_float' : fields.float('Maximum decimal number'),
192 'validation_minimum_date' : fields.date('Minimum date'),
193 'validation_maximum_date' : fields.date('Maximum date'),
194 'validation_valid_err_msg' : fields.text('Error message'),
195 'numeric_required_sum' : fields.integer('Sum of all choices'),
196 'numeric_required_sum_err_msg' : fields.text('Error message'),
197 'rating_allow_one_column_require' : fields.boolean('Allow Only One Response per Column (Forced Ranking)'),
198 'in_visible_rating_weight':fields.boolean('Is Rating Scale Invisible?'),
199 'in_visible_menu_choice':fields.boolean('Is Menu Choice Invisible?'),
200 'comment_column':fields.boolean('Add comment column in matrix'),
201 'column_name':fields.char('Column Name',size=256),
202 'no_of_rows' : fields.integer('No of Rows'),
205 'sequence' : lambda * a: 1,
206 'type' : lambda * a: 'multiple_choice_multiple_ans',
207 'req_error_msg' : lambda * a: 'This question requires an answer.',
208 'required_type' : lambda * a: '',
209 'comment_label' : lambda * a: 'Other',
210 'comment_valid_type' : lambda * a: 'do_not_validate',
211 'comment_valid_err_msg' : lambda * a : 'The comment you entered is in an invalid format.',
212 'validation_type' : lambda * a: 'do_not_validate',
213 'validation_valid_err_msg' : lambda * a : 'The comment you entered is in an invalid format.',
214 'numeric_required_sum_err_msg' : lambda * a :'The choices need to add up to [enter sum here].',
215 'make_comment_field_err_msg' : lambda * a : 'Please enter a comment.',
218 def on_change_type(self, cr, uid, ids, type, context=None):
219 if type in ['rating_scale']:
220 return {'value': {'in_visible_rating_weight':False,'in_visible_menu_choice':True}}
221 elif type in ['matrix_of_drop_down_menus']:
222 return {'value': {'in_visible_rating_weight':True,'in_visible_menu_choice':False}}
223 elif type in ['single_textbox']:
224 return {'value': {'in_visible_rating_weight':True,'in_visible_menu_choice':True}}
226 return {'value': {'in_visible_rating_weight':True,'in_visible_menu_choice':True}}
228 def write(self, cr, uid, ids, vals, context=None):
229 questions = self.read(cr,uid, ids, ['answer_choice_ids', 'type', 'required_type','req_ans', 'minimum_req_ans', 'maximum_req_ans', 'column_heading_ids'])
230 for question in questions:
231 col_len = len(question['column_heading_ids'])
232 if vals.has_key('column_heading_ids'):
233 for col in vals['column_heading_ids']:
234 if type(col[2]) == type({}):
238 if vals.has_key('type'):
239 que_type = vals['type']
241 que_type = question['type']
242 if que_type in ['matrix_of_choices_only_one_ans', 'matrix_of_choices_only_multi_ans', 'matrix_of_drop_down_menus', 'rating_scale']:
244 raise osv.except_osv(_('Error !'),_("You must enter one or more column heading."))
246 ans_len = len(question['answer_choice_ids'])
247 if vals.has_key('answer_choice_ids'):
248 for ans in vals['answer_choice_ids']:
249 if type(ans[2]) == type({}):
253 if que_type not in ['descriptive_text', 'single_textbox', 'comment','table']:
255 raise osv.except_osv(_('Error !'),_("You must enter one or more Answer."))
258 if vals.has_key('required_type'):
259 req_type = vals['required_type']
261 req_type = question['required_type']
262 if req_type in ['at least', 'at most', 'exactly']:
263 if vals.has_key('req_ans'):
264 if not vals['req_ans'] or vals['req_ans'] > ans_len:
265 raise osv.except_osv(_('Error !'),_("#Required Answer you entered is greater than the number of answer. Please use a number that is smaller than %d.") % (ans_len + 1))
267 if not question['req_ans'] or question['req_ans'] > ans_len:
268 raise osv.except_osv(_('Error !'),_("#Required Answer you entered is greater than the number of answer. Please use a number that is smaller than %d.") % (ans_len + 1))
270 if req_type == 'a range':
273 if vals.has_key('minimum_req_ans'):
274 minimum_ans = vals['minimum_req_ans']
275 if not vals['minimum_req_ans'] or vals['minimum_req_ans'] > ans_len:
276 raise osv.except_osv(_('Error !'),_("Minimum Required Answer you entered is greater than the number of answer. Please use a number that is smaller than %d.") % (ans_len + 1))
278 minimum_ans = question['minimum_req_ans']
279 if not question['minimum_req_ans'] or question['minimum_req_ans'] > ans_len:
280 raise osv.except_osv(_('Error !'),_("Minimum Required Answer you entered is greater than the number of answer. Please use a number that is smaller than %d.") % (ans_len + 1))
281 if vals.has_key('maximum_req_ans'):
282 maximum_ans = vals['maximum_req_ans']
283 if not vals['maximum_req_ans'] or vals['maximum_req_ans'] > ans_len:
284 raise osv.except_osv(_('Error !'),_("Maximum Required Answer you entered for your maximum is greater than the number of answer. Please use a number that is smaller than %d.") % (ans_len + 1))
286 maximum_ans = question['maximum_req_ans']
287 if not question['maximum_req_ans'] or question['maximum_req_ans'] > ans_len:
288 raise osv.except_osv(_('Error !'),_("Maximum Required Answer you entered for your maximum is greater than the number of answer. Please use a number that is smaller than %d.") % (ans_len + 1))
289 if maximum_ans <= minimum_ans:
290 raise osv.except_osv(_('Error !'),_("Maximum Required Answer is greater than Minimum Required Answer"))
291 if question['type'] == 'matrix_of_drop_down_menus' and vals.has_key('column_heading_ids'):
292 for col in vals['column_heading_ids']:
293 if col[2].has_key('menu_choice') and not col[2]['menu_choice']:
294 raise osv.except_osv(_('Error !'),_("You must enter one or more menu choices in column heading"))
295 elif col[2].has_key('menu_choice') and col[2]['menu_choice'].strip() == '':
296 raise osv.except_osv(_('Error !'),_("You must enter one or more menu choices in column heading (white spaces not allowed)"))
297 return super(survey_question, self).write(cr, uid, ids, vals, context=context)
299 def create(self, cr, uid, vals, context):
302 if vals.has_key('answer_choice_ids') and not len(vals['answer_choice_ids']):
303 if vals.has_key('type') and vals['type'] not in ['descriptive_text', 'single_textbox', 'comment','table']:
304 raise osv.except_osv(_('Error !'),_("You must enter one or more answer."))
305 if vals.has_key('column_heading_ids') and not len(vals['column_heading_ids']):
306 if vals.has_key('type') and vals['type'] in ['matrix_of_choices_only_one_ans', 'matrix_of_choices_only_multi_ans', 'matrix_of_drop_down_menus', 'rating_scale']:
307 raise osv.except_osv(_('Error !'),_("You must enter one or more column heading."))
308 if vals.has_key('required_type') and vals['required_type'] in ['at least', 'at most', 'exactly']:
309 if vals['req_ans'] > len(vals['answer_choice_ids']) or not vals['req_ans']:
310 raise osv.except_osv(_('Error !'),_("#Required Answer you entered is greater than the number of answer. Please use a number that is smaller than %d.") % (len(vals['answer_choice_ids'])+1))
311 if vals.has_key('required_type') and vals['required_type'] == 'a range':
312 minimum_ans = vals['minimum_req_ans']
313 maximum_ans = vals['maximum_req_ans']
314 if vals['minimum_req_ans'] > len(vals['answer_choice_ids']) or not vals['minimum_req_ans']:
315 raise osv.except_osv(_('Error !'),_("Minimum Required Answer you entered is greater than the number of answer. Please use a number that is smaller than %d.") % (len(vals['answer_choice_ids'])+1))
316 if vals['maximum_req_ans'] > len(vals['answer_choice_ids']) or not vals['maximum_req_ans']:
317 raise osv.except_osv(_('Error !'),_("Maximum Required Answer you entered for your maximum is greater than the number of answer. Please use a number that is smaller than %d.") % (len(vals['answer_choice_ids'])+1))
318 if maximum_ans <= minimum_ans:
319 raise osv.except_osv(_('Error !'),_("Maximum Required Answer is greater than Minimum Required Answer"))
320 if vals['type'] == 'matrix_of_drop_down_menus':
321 for col in vals['column_heading_ids']:
322 if not col[2]['menu_choice']:
323 raise osv.except_osv(_('Error !'),_("You must enter one or more menu choices in column heading"))
324 elif col[2]['menu_choice'].strip() == '':
325 raise osv.except_osv(_('Error !'),_("You must enter one or more menu choices in column heading (white spaces not allowed)"))
327 res = super(survey_question, self).create(cr, uid, vals, context)
330 def default_get(self, cr, uid, fields, context={}):
331 data = super(survey_question, self).default_get(cr, uid, fields, context)
332 if context.has_key('line_order') and context['line_order']:
333 if len(context['line_order'][-1]) > 2 and context['line_order'][-1][2].has_key('sequence'):
334 data['sequence'] = context['line_order'][-1][2]['sequence'] + 1
340 class survey_tbl_column_heading(osv.osv):
341 _name = 'survey.tbl.column.heading'
343 'name' : fields.char('Column', size=255),
344 'question_id' : fields.many2one('survey.question', 'Question', ondelete='cascade'),
346 survey_tbl_column_heading()
348 class survey_question_column_heading(osv.osv):
349 _name = 'survey.question.column.heading'
350 _description = 'Survey Question Column Heading'
353 def _get_in_visible_rating_weight(self,cr, uid, context={}):
354 if context.get('in_visible_rating_weight',False):
355 return context['in_visible_rating_weight']
357 def _get_in_visible_menu_choice(self,cr, uid, context={}):
358 if context.get('in_visible_menu_choice',False):
359 return context['in_visible_menu_choice']
363 'title' : fields.char('Column Heading', size=128, required=1),
364 'menu_choice' : fields.text('Menu Choice'),
365 'rating_weight' : fields.integer('Weight'),
366 'question_id' : fields.many2one('survey.question', 'Question', ondelete='cascade'),
367 'in_visible_rating_weight':fields.boolean('Is Rating Scale Invisible ??'),
368 'in_visible_menu_choice':fields.boolean('Is Menu Choice Invisible??')
371 'in_visible_rating_weight':_get_in_visible_rating_weight,
372 'in_visible_menu_choice':_get_in_visible_menu_choice,
374 survey_question_column_heading()
376 class survey_answer(osv.osv):
377 _name = 'survey.answer'
378 _description = 'Survey Answer'
382 def _calc_response_avg(self, cr, uid, ids, field_name, arg, context):
384 for rec in self.browse(cr, uid, ids):
386 cr.execute("select count(question_id) ,(select count(answer_id) \
387 from survey_response_answer sra, survey_response_line sa \
388 where sra.response_id = sa.id and sra.answer_id = %d \
389 and sa.state='done') as tot_ans from survey_response_line \
390 where question_id = %d and state = 'done'"\
391 % (rec.id, rec.question_id.id))
395 avg = float(res[1]) * 100 / res[0]
400 'average': round(avg, 2),
405 'question_id' : fields.many2one('survey.question', 'Question', ondelete='cascade'),
406 'answer' : fields.char('Answer', size=128, required=1),
407 'sequence' : fields.integer('Sequence'),
408 'response' : fields.function(_calc_response_avg, method=True, string="#Response", multi='sums'),
409 'average' : fields.function(_calc_response_avg, method=True, string="#Avg", multi='sums'),
412 'sequence' : lambda * a: 1
415 def default_get(self, cr, uid, fields, context={}):
416 data = super(survey_answer, self).default_get(cr, uid, fields, context)
417 if context.has_key('line_order') and context['line_order']:
418 if len(context['line_order'][-1]) > 2 and context['line_order'][-1][2].has_key('sequence'):
419 data['sequence'] = context['line_order'][-1][2]['sequence'] + 1
424 class survey_response(osv.osv):
425 _name = "survey.response"
426 _rec_name = 'date_create'
428 'survey_id' : fields.many2one('survey', 'Survey', required=1),
429 'date_create' : fields.datetime('Create Date', required=1),
430 'user_id' : fields.many2one('res.users', 'User'),
431 'response_type' : fields.selection([('manually', 'Manually'), ('link', 'Link')], 'Response Type', required=1),
432 'question_ids' : fields.one2many('survey.response.line', 'response_id', 'Response Answer'),
437 class survey_response_line(osv.osv):
438 _name = 'survey.response.line'
439 _description = 'Survey Response Line'
440 _rec_name = 'date_create'
442 'response_id' : fields.many2one('survey.response', 'Response', ondelete='cascade'),
443 'date_create' : fields.datetime('Create Date', required=1),
444 'state' : fields.selection([('draft', 'Draft'), ('done', 'Answered'),('skip', 'Skiped')], 'Status', readonly=True),
445 'question_id' : fields.many2one('survey.question', 'Question', ondelete='cascade'),
446 'page_id' : fields.related('question_id', 'page_id', type='many2one', relation='survey.page', string='Page'),
447 'response_answer_ids' : fields.one2many('survey.response.answer', 'response_id', 'Response Answer'),
448 'comment' : fields.text('Notes'),
449 'single_text' : fields.char('Text', size=255),
452 'state' : lambda * a: "draft",
455 def response_draft(self, cr, uid, ids, arg):
456 self.write(cr, uid, ids, { 'state' : 'draft' })
459 def response_done(self, cr, uid, ids, arg):
460 self.write(cr, uid, ids, { 'state' : 'done' })
463 def response_skip(self, cr, uid, ids, arg):
464 self.write(cr, uid, ids, { 'state' : 'skip' })
467 survey_response_line()
469 class survey_response_answer(osv.osv):
470 _name = 'survey.response.answer'
471 _description = 'Survey Response Answer'
472 _rec_name = 'response_id'
474 'response_id' : fields.many2one('survey.response.line', 'Response', ondelete='cascade'),
475 'answer_id' : fields.many2one('survey.answer', 'Answer', required=1, ondelete='cascade'),
476 'answer' : fields.char('Value', size =255),
477 'value_choice' : fields.char('Value Choice', size =255),
478 'comment' : fields.text('Notes'),
479 'comment_field' : fields.char('Comment', size = 255)
481 survey_response_answer()
484 class survey_name_wiz(osv.osv_memory):
485 _name = 'survey.name.wiz'
487 def _get_survey(self, cr, uid, context=None):
488 surv_obj = self.pool.get("survey")
490 if context.has_key('survey_id'):
491 for sur in surv_obj.browse(cr, uid, [context['survey_id']]):
492 result.append((sur.id, sur.title))
494 group_id = self.pool.get('res.groups').search(cr, uid, [('name', '=', 'Survey / Manager')])
495 user_obj = self.pool.get('res.users')
496 user_rec = user_obj.read(cr, uid, uid)
497 for sur in surv_obj.browse(cr, uid, surv_obj.search(cr, uid, [])):
498 if sur.state == 'open':
499 if group_id[0] in user_rec['groups_id']:
500 result.append((sur.id, sur.title))
501 elif sur.id in user_rec['survey_id']:
502 result.append((sur.id, sur.title))
506 'survey_id': fields.selection(_get_survey, "Survey", required="1"),
507 'page_no' : fields.integer('Page Number'),
508 'note' : fields.text("Description"),
509 'page' : fields.char('Page Position',size = 12),
510 'transfer' : fields.boolean('Page Transfer'),
511 'store_ans' : fields.text('Store Answer'),
512 'response' : fields.char('Response',size=16)
515 'page_no' : lambda * a: - 1,
516 'page' : lambda * a: 'next',
517 'transfer' : lambda * a: 1,
518 'response' : lambda * a: 0,
521 def action_next(self, cr, uid, ids, context=None):
522 sur_id = self.read(cr, uid, ids, [])[0]
523 survey_id = sur_id['survey_id']
524 context.update({'survey_id' : survey_id, 'sur_name_id' : sur_id['id']})
525 cr.execute('select count(id) from survey_history where user_id=%s\
526 and survey_id=%s' % (uid,survey_id))
527 res = cr.fetchone()[0]
528 user_limit = self.pool.get('survey').read(cr, uid, survey_id, ['response_user'])['response_user']
529 if user_limit and res >= user_limit:
530 raise osv.except_osv(_('Warning !'),_("You can not give response for this survey more than %s times") % (user_limit))
531 his_id = self.pool.get('survey.history').create(cr, uid, {'user_id': uid, \
532 'date': strftime('%Y-%m-%d %H:%M:%S'),\
533 'survey_id': survey_id})
534 survey_obj = self.pool.get('survey')
535 sur_rec = survey_obj.read(cr,uid,self.read(cr,uid,ids)[0]['survey_id'])
536 survey_obj.write(cr, uid, survey_id, {'tot_start_survey' : sur_rec['tot_start_survey'] + 1})
538 search_obj = self.pool.get('ir.ui.view')
539 search_id = search_obj.search(cr,uid,[('model','=','survey.question.wiz'),('name','=','Survey Search')])
544 'res_model': 'survey.question.wiz',
545 'type': 'ir.actions.act_window',
547 'search_view_id':search_id[0],
551 def on_change_survey(self, cr, uid, ids, survey_id, context=None):
552 notes = self.pool.get('survey').read(cr, uid, survey_id, ['note'])['note']
553 return {'value': {'note' : notes}}
557 class survey_question_wiz(osv.osv_memory):
558 _name = 'survey.question.wiz'
560 'name': fields.integer('Number'),
563 def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False,submenu=False):
564 result = super(survey_question_wiz, self).fields_view_get(cr, uid, view_id, view_type, context, toolbar,submenu)
565 surv_name_wiz = self.pool.get('survey.name.wiz')
566 if view_type in ['form']:
567 sur_name_rec = surv_name_wiz.read(cr, uid, context['sur_name_id'])
568 survey_id = context['survey_id']
569 survey_obj = self.pool.get('survey')
570 sur_rec = survey_obj.read(cr, uid, survey_id, [])
571 page_obj = self.pool.get('survey.page')
572 que_obj = self.pool.get('survey.question')
573 ans_obj = self.pool.get('survey.answer')
574 response_obj = self.pool.get('survey.response.line')
575 que_col_head = self.pool.get('survey.question.column.heading')
576 tbl_col = self.pool.get('survey.tbl.column.heading')
577 p_id = sur_rec['page_ids']
578 total_pages = len(p_id)
580 if not sur_name_rec['page_no'] + 1 :
581 surv_name_wiz.write(cr, uid, [context['sur_name_id']], {'store_ans':{}})
582 sur_name_read = surv_name_wiz.read(cr, uid, context['sur_name_id'])
583 page_number = int(sur_name_rec['page_no'])
584 if sur_name_read['transfer'] or not sur_name_rec['page_no'] + 1 :
585 surv_name_wiz.write(cr, uid, [context['sur_name_id']], {'transfer':False})
587 if sur_name_read['page'] == "next" or sur_name_rec['page_no'] == - 1 :
588 if len(p_id) > sur_name_rec['page_no'] + 1 :
589 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:
590 survey_obj.write(cr, uid, survey_id, {'state':'close', 'date_close':strftime("%Y-%m-%d %H:%M:%S")})
591 p_id = p_id[sur_name_rec['page_no'] + 1]
592 surv_name_wiz.write(cr, uid, [context['sur_name_id']], {'page_no' : sur_name_rec['page_no'] + 1})
595 if sur_name_rec['page_no'] > - 1:
598 if sur_name_rec['page_no'] != 0:
599 p_id = p_id[sur_name_rec['page_no'] - 1]
600 surv_name_wiz.write(cr, uid, [context['sur_name_id']], {'page_no' : sur_name_rec['page_no'] - 1})
603 if sur_name_rec['page_no'] > 1:
607 pag_rec = page_obj.read(cr, uid, p_id)
608 xml_form = etree.Element('form', {'string': _(tools.ustr(pag_rec['title']))})
609 etree.SubElement(xml_form, 'label', {'string': to_xml(tools.ustr(pag_rec['note'] or '')), 'align': '0.0', 'colspan':'4'})
610 que_ids = pag_rec['question_ids']
614 que_rec = que_obj.read(cr, uid, que)
615 descriptive_text = ""
616 separator_string = tools.ustr(qu_no) + "." + tools.ustr(que_rec['question'])
617 xml_group = etree.SubElement(xml_form, 'group', {'col': '1', 'colspan': '4'})
618 etree.SubElement(xml_group, 'separator', {'string': to_xml(separator_string), 'colspan': '4'})
619 ans_ids = ans_obj.read(cr, uid, que_rec['answer_choice_ids'], [])
620 if que_rec['type'] == 'multiple_choice_only_one_ans':
623 selection.append((tools.ustr(ans['id']), ans['answer']))
624 xml_group = etree.SubElement(xml_group, 'group', {'col': '2', 'colspan': '2'})
625 etree.SubElement(xml_group, 'field', {'name': tools.ustr(que) + "_selection"})
626 fields[tools.ustr(que) + "_selection"] = {'type':'selection', 'selection' :selection, 'string':"Answer"}
627 elif que_rec['type'] == 'multiple_choice_multiple_ans':
628 xml_group = etree.SubElement(xml_group, 'group', {'col': '4', 'colspan': '4'})
630 etree.SubElement(xml_group, 'field', {'name': tools.ustr(que) + "_" + tools.ustr(ans['id'])})
631 fields[tools.ustr(que) + "_" + tools.ustr(ans['id'])] = {'type':'boolean', 'string':ans['answer']}
632 elif que_rec['type'] in ['matrix_of_choices_only_one_ans', 'rating_scale']:
633 if que_rec['comment_column']:
639 xml_group = etree.SubElement(xml_group, 'group', {'col': tools.ustr(col), 'colspan': tools.ustr(colspan)})
641 etree.SubElement(xml_group, 'newline')
642 etree.SubElement(xml_group, 'field', {'name': tools.ustr(que) + "_selection_" + tools.ustr(row['id']),'string':to_xml(tools.ustr(row['answer']))})
643 selection = [('','')]
644 for col in que_col_head.read(cr, uid, que_rec['column_heading_ids']):
645 selection.append((col['title'], col['title']))
646 fields[tools.ustr(que) + "_selection_" + tools.ustr(row['id'])] = {'type':'selection', 'selection' : selection, 'string': "Answer"}
647 if que_rec['comment_column']:
648 fields[tools.ustr(que) + "_commentcolumn_"+tools.ustr(row['id']) + "_field"] = {'type':'char', 'size' : 255, 'string':tools.ustr(que_rec['column_name']), 'views':{}}
649 etree.SubElement(xml_group, 'field', {'name': tools.ustr(que) + "_commentcolumn_"+tools.ustr(row['id'])+ "_field"})
650 elif que_rec['type'] == 'matrix_of_choices_only_multi_ans':
651 xml_group = etree.SubElement(xml_group, 'group', {'col': '2', 'colspan': '2'})
653 etree.SubElement(xml_group, 'label', {'string': to_xml(tools.ustr(row['answer'])) +' :-', 'align': '0.0'})
654 etree.SubElement(xml_group, 'newline')
655 for col in que_col_head.read(cr, uid, que_rec['column_heading_ids']):
656 etree.SubElement(xml_group, 'field', {'name': tools.ustr(que) + "_" + tools.ustr(row['id']) + "_" + tools.ustr(col['title'])})
657 fields[tools.ustr(que) + "_" + tools.ustr(row['id']) + "_" + tools.ustr(col['title'])] = {'type':'boolean', 'string': col['title']}
658 elif que_rec['type'] == 'matrix_of_drop_down_menus':
659 xml_group = etree.SubElement(xml_group, 'group', {'col': '2', 'colspan': '2'})
661 etree.SubElement(xml_group, 'label', {'string': to_xml(tools.ustr(row['answer']))+' :-', 'align': '0.0'})
662 etree.SubElement(xml_group, 'newline')
663 for col in que_col_head.read(cr, uid, que_rec['column_heading_ids']):
665 if col['menu_choice']:
666 for item in col['menu_choice'].split('\n'):
667 if item and not item.strip() == '': selection.append((item ,item))
668 etree.SubElement(xml_group, 'field', {'name': tools.ustr(que) + "_" + tools.ustr(row['id']) + "_" + tools.ustr(col['title'])})
669 fields[tools.ustr(que) + "_" + tools.ustr(row['id']) + "_" + tools.ustr(col['title'])] = {'type':'selection', 'string': col['title'], 'selection':selection}
670 elif que_rec['type'] == 'multiple_textboxes':
671 xml_group = etree.SubElement(xml_group, 'group', {'col': '1', 'colspan': '4'})
673 etree.SubElement(xml_group, 'field', {'name': tools.ustr(que) + "_" + tools.ustr(ans['id']) + "_multi"})
674 fields[tools.ustr(que) + "_" + tools.ustr(ans['id']) + "_multi"] = {'type':'char', 'size':255, 'string':ans['answer']}
675 elif que_rec['type'] == 'numerical_textboxes':
676 xml_group = etree.SubElement(xml_group, 'group', {'col': '2', 'colspan': '2'})
678 etree.SubElement(xml_group, 'field', {'name': tools.ustr(que) + "_" + tools.ustr(ans['id']) + "_numeric"})
679 fields[tools.ustr(que) + "_" + tools.ustr(ans['id']) + "_numeric"] = {'type':'integer', 'string':ans['answer']}
680 elif que_rec['type'] == 'date':
681 xml_group = etree.SubElement(xml_group, 'group', {'col': '2', 'colspan': '2'})
683 etree.SubElement(xml_group, 'field', {'name': tools.ustr(que) + "_" + tools.ustr(ans['id'])})
684 fields[tools.ustr(que) + "_" + tools.ustr(ans['id'])] = {'type':'date', 'string':ans['answer']}
685 elif que_rec['type'] == 'date_and_time':
686 xml_group = etree.SubElement(xml_group, 'group', {'col': '2', 'colspan': '2'})
688 etree.SubElement(xml_group, 'field', {'name': tools.ustr(que) + "_" + tools.ustr(ans['id'])})
689 fields[tools.ustr(que) + "_" + tools.ustr(ans['id'])] = {'type':'datetime', 'string':ans['answer']}
690 elif que_rec['type'] == 'descriptive_text':
691 etree.SubElement(xml_group, 'label', {'string': to_xml(tools.ustr(que_rec['descriptive_text']))})
692 elif que_rec['type'] == 'single_textbox':
693 etree.SubElement(xml_group, 'field', {'name': tools.ustr(que) + "_single", 'nolabel':"1" ,'colspan':"4"})
694 fields[tools.ustr(que) + "_single"] = {'type':'char', 'size' : 255, 'string':"single_textbox", 'views':{}}
695 elif que_rec['type'] == 'comment':
696 etree.SubElement(xml_group, 'field', {'name': tools.ustr(que) + "_comment", 'nolabel':"1" ,'colspan':"4"})
697 fields[tools.ustr(que) + "_comment"] = {'type':'text', 'string':"Comment/Eassy Box", 'views':{}}
698 elif que_rec['type'] == 'table':
699 xml_group = etree.SubElement(xml_group, 'group', {'col': str(len(que_rec['column_ids'])), 'colspan': '4'})
700 for col in tbl_col.read(cr, uid, que_rec['column_ids']):
701 etree.SubElement(xml_group, 'separator', {'string': tools.ustr(col['name']),'colspan': '1'})
702 for row in range(0,que_rec['no_of_rows']):
703 for col in tbl_col.read(cr, uid, que_rec['column_ids']):
704 etree.SubElement(xml_group, 'field', {'name': tools.ustr(que) +"_"+ tools.ustr(row)+ tools.ustr(col['name']), 'nolabel':"1"})
705 fields[tools.ustr(que)+"_"+ tools.ustr(row)+tools.ustr(col['name'])] = {'type':'char','size':255,'views':{}}
706 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']:
707 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']:
708 etree.SubElement(xml_group, 'field', {'name': tools.ustr(que) + "_otherfield", 'colspan':"4"})
709 fields[tools.ustr(que) + "_otherfield"] = {'type':'boolean', 'string':que_rec['comment_label'], 'views':{}}
710 if que_rec['comment_field_type'] == 'char':
711 etree.SubElement(xml_group, 'field', {'name': tools.ustr(que) + "_other", 'nolabel':"1" ,'colspan':"4"})
712 fields[tools.ustr(que) + "_other"] = {'type': 'char', 'string': '', 'size':255, 'views':{}}
713 elif que_rec['comment_field_type'] == 'text':
714 etree.SubElement(xml_group, 'field', {'name': tools.ustr(que) + "_other", 'nolabel':"1" ,'colspan':"4"})
715 fields[tools.ustr(que) + "_other"] = {'type': 'text', 'string': '', 'views':{}}
717 if que_rec['comment_field_type'] == 'char':
718 etree.SubElement(xml_group, 'label', {'string': to_xml(tools.ustr(que_rec['comment_label'])),'colspan':"4"})
719 etree.SubElement(xml_group, 'field', {'name': tools.ustr(que) + "_other", 'nolabel':"1" ,'colspan':"4"})
720 fields[tools.ustr(que) + "_other"] = {'type': 'char', 'string': '', 'size':255, 'views':{}}
721 elif que_rec['comment_field_type'] == 'text':
722 etree.SubElement(xml_group, 'label', {'string': to_xml(tools.ustr(que_rec['comment_label'])),'colspan':"4"})
723 etree.SubElement(xml_group, 'field', {'name': tools.ustr(que) + "_other", 'nolabel':"1" ,'colspan':"4"})
724 fields[tools.ustr(que) + "_other"] = {'type': 'text', 'string': '', 'views':{}}
725 etree.SubElement(xml_form, 'separator', {'colspan': '4'})
726 xml_group = etree.SubElement(xml_form, 'group', {'col': '6', 'colspan': '4'})
727 etree.SubElement(xml_group, 'field', {'name': 'progress_bar_' + tools.ustr(page_number) , 'widget':'progressbar'})
728 fields['progress_bar_' + tools.ustr(page_number)] = {'type':'int', 'string':"Progress", 'views':{}}
729 etree.SubElement(xml_group, 'label', {'string': tools.ustr(page_number+ 1) + "/" + tools.ustr(total_pages)})
730 etree.SubElement(xml_group, 'button', {'icon': "gtk-cancel", 'special': "cancel",'string':"Cancel"})
732 etree.SubElement(xml_group, 'button', {'colspan':"1",'icon':"gtk-go-back",'name':"action_previous",'string':"Previous",'type':"object"})
733 etree.SubElement(xml_group, 'button', {'icon': "gtk-go-forward", 'name':"action_next",'string':"Next",'type':"object"})
734 root = xml_form.getroottree()
735 root.write('/tmp/arch4.xml', pretty_print=True)
736 result['arch'] = etree.tostring(root)
737 result['fields'] = fields
738 result['context'] = context
740 if not context.has_key('active'):
741 survey_obj.write(cr, uid, survey_id, {'tot_comp_survey' : sur_rec['tot_comp_survey'] + 1})
742 xml_form = etree.Element('form', {'string': _('Complete Survey Response')})
743 etree.SubElement(xml_form, 'separator', {'string': 'Complete Survey', 'colspan': "4"})
744 etree.SubElement(xml_form, 'label', {'string': 'Thanks for your response'})
745 etree.SubElement(xml_form, 'newline')
746 etree.SubElement(xml_form, 'button', {'icon': "gtk-go-forward", 'special':"cancel",'string':"OK",'colspan':"2"})
747 root = xml_form.getroottree()
748 result['arch'] = etree.tostring(root)
749 result['fields'] = {}
750 result['context'] = context
753 def default_get(self, cr, uid, fields_list, context=None):
755 for field in fields_list:
756 if field.split('_')[0] == 'progress':
757 tot_page_id = self.pool.get('survey').browse(cr, uid, context['survey_id'])
758 tot_per = (float(100) * (int(field.split('_')[2]) + 1) / len(tot_page_id.page_ids))
759 value[field] = tot_per
760 if context.has_key('active') and context['active']:
762 surv_name_wiz = self.pool.get('survey.name.wiz')
763 sur_name_read = surv_name_wiz.read(cr, uid, context['sur_name_id'])
766 for key,val in sur_name_read['store_ans'].items():
767 for field in fields_list:
768 if field in list(val):
769 value[field] = val[field]
772 def create(self, cr, uid, vals, context=None):
773 if context.has_key('active') and context['active']:
775 for key,val in vals.items():
776 if key.split('_')[0] == "progress":
781 surv_name_wiz = self.pool.get('survey.name.wiz')
782 surv_all_resp_obj = self.pool.get('survey.response')
783 sur_name_read = surv_name_wiz.read(cr, uid, context['sur_name_id'])
785 if not sur_name_read['response']:
786 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']})
787 surv_name_wiz.write(cr, uid, [context['sur_name_id']], {'response' : tools.ustr(response_id)})
789 response_id = int(sur_name_read['response'])
790 for key,val in sur_name_read['store_ans'].items():
792 if field.split('_')[0] == val['question_id']:
794 click_update.append(key)
796 resp_obj = self.pool.get('survey.response.line')
797 res_ans_obj = self.pool.get('survey.response.answer')
798 que_obj = self.pool.get('survey.question')
802 for key, val in vals.items():
803 que_id = key.split('_')[0]
804 if que_id not in que_li:
805 que_li.append(que_id)
806 que_rec = que_obj.read(cr, uid, [que_id], [])[0]
807 resp_id = resp_obj.create(cr, uid, {'question_id':que_id, 'date_create':datetime.datetime.now(), \
808 'state':'done','response_id' : response_id })
809 resp_id_list.append(resp_id)
810 sur_name_read['store_ans'].update({resp_id:{'question_id':que_id}})
811 surv_name_wiz.write(cr, uid, [context['sur_name_id']], {'store_ans':sur_name_read['store_ans']})
816 comment_field = False
817 comment_value = False
819 for key1, val1 in vals.items():
820 if val1 and key1.split('_')[1] == "otherfield" and key1.split('_')[0] == que_id:
822 sur_name_read['store_ans'][resp_id].update({key1:val1})
824 surv_name_wiz.write(cr, uid, [context['sur_name_id']], {'store_ans':sur_name_read['store_ans']})
826 elif val1 and key1.split('_')[1] == "selection" and key1.split('_')[0] == que_id:
827 if len(key1.split('_')) > 2:
828 ans_create_id = res_ans_obj.create(cr, uid, {'response_id':resp_id, 'answer_id':key1.split('_')[-1], 'answer' : val1})
829 selected_value.append(val1)
830 response_list.append(str(ans_create_id) + "_" + str(key1.split('_')[-1]))
832 ans_create_id = res_ans_obj.create(cr, uid, {'response_id':resp_id, 'answer_id':val1})
833 sur_name_read['store_ans'][resp_id].update({key1:val1})
835 elif key1.split('_')[1] == "other" and key1.split('_')[0] == que_id:
840 if que_rec['comment_valid_type'] == 'must_be_specific_length':
841 if (not val1 and que_rec['validation_minimum_no']) or len(val1) < que_rec['validation_maximum_no'] or len(val1) > que_rec['comment_maximum_no']:
843 elif que_rec['comment_valid_type'] in ['must_be_whole_number', 'must_be_decimal_number', 'must_be_date']:
846 if que_rec['comment_valid_type'] == 'must_be_whole_number':
848 if value < que_rec['validation_minimum_no'] or value > que_rec['validation_maximum_no']:
850 elif que_rec['comment_valid_type'] == 'must_be_decimal_number':
852 if value < que_rec['comment_minimum_float'] or value > que_rec['comment_maximum_float']:
854 elif que_rec['comment_valid_type'] == 'must_be_date':
855 value = datetime.datetime.strptime(val1, "%Y-%m-%d")
856 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"):
860 elif que_rec['comment_valid_type'] == 'must_be_email_address':
862 if re.match("^[a-zA-Z0-9._%-+]+@[a-zA-Z0-9._%-]+.[a-zA-Z]{2,6}$", val1) == None:
865 for res in resp_id_list:
866 sur_name_read['store_ans'].pop(res)
867 raise osv.except_osv(_('Error !'), _("'" + que_rec['question'] + "' \n" + tools.ustr(que_rec['comment_valid_err_msg'])))
868 resp_obj.write(cr, uid, resp_id, {'comment':val1})
869 sur_name_read['store_ans'][resp_id].update({key1:val1})
870 elif val1 and key1.split('_')[1] == "comment" and key1.split('_')[0] == que_id:
871 resp_obj.write(cr, uid, resp_id, {'comment':val1})
872 sur_name_read['store_ans'][resp_id].update({key1:val1})
874 elif val1 and key1.split('_')[0] == que_id and (key1.split('_')[1] == "single" or (len(key1.split('_')) > 2 and key1.split('_')[2] == 'multi')):
876 if que_rec['validation_type'] == 'must_be_specific_length':
877 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']:
879 elif que_rec['validation_type'] in ['must_be_whole_number', 'must_be_decimal_number', 'must_be_date']:
882 if que_rec['validation_type'] == 'must_be_whole_number':
884 if value < que_rec['validation_minimum_no'] or value > que_rec['validation_maximum_no']:
886 elif que_rec['validation_type'] == 'must_be_decimal_number':
888 if value < que_rec['validation_minimum_float'] or value > que_rec['validation_maximum_float']:
890 elif que_rec['validation_type'] == 'must_be_date':
891 value = datetime.datetime.strptime(val1, "%Y-%m-%d")
892 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"):
896 elif que_rec['validation_type'] == 'must_be_email_address':
898 if re.match("^[a-zA-Z0-9._%-+]+@[a-zA-Z0-9._%-]+.[a-zA-Z]{2,6}$", val1) == None:
901 for res in resp_id_list:
902 sur_name_read['store_ans'].pop(res)
903 raise osv.except_osv(_('Error !'), _("'" + que_rec['question'] + "' \n" + tools.ustr(que_rec['validation_valid_err_msg'])))
904 if key1.split('_')[1] == "single" :
905 resp_obj.write(cr, uid, resp_id, {'single_text':val1})
907 ans_create_id = res_ans_obj.create(cr, uid, {'response_id':resp_id, 'answer_id':key1.split('_')[1], 'answer' : val1})
908 sur_name_read['store_ans'][resp_id].update({key1:val1})
910 elif val1 and que_id == key1.split('_')[0] and len(key1.split('_')) > 2 and key1.split('_')[2] == 'numeric':
911 ans_create_id = res_ans_obj.create(cr, uid, {'response_id':resp_id, 'answer_id':key1.split('_')[1], 'answer' : val1})
912 sur_name_read['store_ans'][resp_id].update({key1:val1})
914 numeric_sum += int(val1)
915 elif val1 and que_id == key1.split('_')[0] and len(key1.split('_')) == 3:
916 if type(val1) == type('') or type(val1) == type(u''):
917 ans_create_id = res_ans_obj.create(cr, uid, {'response_id':resp_id, 'answer_id':key1.split('_')[1], 'answer' : key1.split('_')[2], 'value_choice' : val1})
918 sur_name_read['store_ans'][resp_id].update({key1:val1})
920 ans_create_id = res_ans_obj.create(cr, uid, {'response_id':resp_id, 'answer_id':key1.split('_')[1], 'answer' : key1.split('_')[2]})
921 sur_name_read['store_ans'][resp_id].update({key1:True})
922 matrix_list.append(key1.split('_')[0] + '_' + key1.split('_')[1])
924 elif val1 and que_id == key1.split('_')[0] and len(key1.split('_')) == 2:
925 ans_create_id = res_ans_obj.create(cr, uid, {'response_id':resp_id, 'answer_id':key1.split('_')[-1], 'answer' : val1})
926 sur_name_read['store_ans'][resp_id].update({key1:val1})
928 surv_name_wiz.write(cr, uid, [context['sur_name_id']], {'store_ans':sur_name_read['store_ans']})
929 for key,val in vals.items():
930 if val and key.split('_')[1] == "commentcolumn" and key.split('_')[0] == que_id:
931 for res_id in response_list:
932 if key.split('_')[2] in res_id.split('_')[1]:
933 a = res_ans_obj.write(cr, uid, [res_id.split('_')[0]], {'comment_field':val})
934 sur_name_read['store_ans'][resp_id].update({key:val})
935 if comment_field and comment_value:
936 for res in resp_id_list:
937 sur_name_read['store_ans'].pop(res)
938 raise osv.except_osv(_('Error re !'), _("'" + que_rec['question'] + "' " + tools.ustr(que_rec['make_comment_field_err_msg'])))
939 if que_rec['type'] == "rating_scale" and que_rec['rating_allow_one_column_require'] and len(selected_value) > len(list(set(selected_value))):
940 for res in resp_id_list:
941 sur_name_read['store_ans'].pop(res)
942 raise osv.except_osv(_('Error re !'), _("'" + que_rec['question'] + "\n you cannot select same answer more than one times'"))
944 resp_obj.write(cr, uid, resp_id, {'state':'skip'})
945 if que_rec['numeric_required_sum'] and numeric_sum > que_rec['numeric_required_sum']:
946 for res in resp_id_list:
947 sur_name_read['store_ans'].pop(res)
948 raise osv.except_osv(_('Error re !'), _("'" + que_rec['question'] + "' " + tools.ustr(que_rec['numeric_required_sum_err_msg'])))
949 if que_rec['type'] in ['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['required_type']:
951 if (que_rec['required_type'] == 'all' and len(list(set(matrix_list))) < len(que_rec['answer_choice_ids'])) or \
952 (que_rec['required_type'] == 'at least' and len(list(set(matrix_list))) < que_rec['req_ans']) or \
953 (que_rec['required_type'] == 'at most' and len(list(set(matrix_list))) > que_rec['req_ans']) or \
954 (que_rec['required_type'] == 'exactly' and len(list(set(matrix_list))) != que_rec['req_ans']) or \
955 (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'])):
956 for res in resp_id_list:
957 sur_name_read['store_ans'].pop(res)
958 raise osv.except_osv(_('Error !'), _("'" + que_rec['question'] + "' " + tools.ustr(que_rec['req_error_msg'])))
959 elif (que_rec['required_type'] == 'all' and select_count < len(que_rec['answer_choice_ids'])) or \
960 (que_rec['required_type'] == 'at least' and select_count < que_rec['req_ans']) or \
961 (que_rec['required_type'] == 'at most' and select_count > que_rec['req_ans']) or \
962 (que_rec['required_type'] == 'exactly' and select_count != que_rec['req_ans']) or \
963 (que_rec['required_type'] == 'a range' and (select_count < que_rec['minimum_req_ans'] or select_count > que_rec['maximum_req_ans'])):
964 for res in resp_id_list:
965 sur_name_read['store_ans'].pop(res)
966 raise osv.except_osv(_('Error !'), _("'" + que_rec['question'] + "' " + tools.ustr(que_rec['req_error_msg'])))
967 if que_rec['type'] in ['multiple_choice_only_one_ans','single_textbox','comment'] and que_rec['is_require_answer'] and select_count <= 0:
968 for res in resp_id_list:
969 sur_name_read['store_ans'].pop(res)
970 raise osv.except_osv(_('Error re !'), _("'" + que_rec['question'] + "' " + tools.ustr(que_rec['req_error_msg'])))
974 for update in click_update:
975 que_rec = que_obj.read(cr, uid , [sur_name_read['store_ans'][update]['question_id']], [])[0]
976 res_ans_obj.unlink(cr, uid,res_ans_obj.search(cr, uid, [('response_id', '=', update)]))
977 resp_id_list.append(update)
978 sur_name_read['store_ans'].update({update:{'question_id':sur_name_read['store_ans'][update]['question_id']}})
979 surv_name_wiz.write(cr, uid, [context['sur_name_id']], {'store_ans':sur_name_read['store_ans']})
984 comment_field = False
985 comment_value = False
987 for key, val in vals.items():
988 ans_id_len = key.split('_')
989 if ans_id_len[0] == sur_name_read['store_ans'][update]['question_id']:
990 if val and key.split('_')[1] == "otherfield" :
992 sur_name_read['store_ans'][update].update({key:val})
994 surv_name_wiz.write(cr, uid, [context['sur_name_id']], {'store_ans':sur_name_read['store_ans']})
996 elif val and key.split('_')[1] == "selection":
997 if len(key.split('_')) > 2:
998 ans_create_id = res_ans_obj.create(cr, uid, {'response_id':update, 'answer_id':key.split('_')[-1], 'answer' : val})
999 selected_value.append(val)
1000 response_list.append(str(ans_create_id) + "_" + str(key.split('_')[-1]))
1002 ans_create_id = res_ans_obj.create(cr, uid, {'response_id':update, 'answer_id': val})
1003 resp_obj.write(cr, uid, update, {'state': 'done'})
1004 sur_name_read['store_ans'][update].update({key:val})
1006 elif key.split('_')[1] == "other":
1008 comment_value = True
1011 if que_rec['comment_valid_type'] == 'must_be_specific_length':
1012 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']:
1014 elif que_rec['comment_valid_type'] in ['must_be_whole_number', 'must_be_decimal_number', 'must_be_date']:
1016 if que_rec['comment_valid_type'] == 'must_be_whole_number':
1018 if value < que_rec['comment_minimum_no'] or value > que_rec['comment_maximum_no']:
1020 elif que_rec['comment_valid_type'] == 'must_be_decimal_number':
1022 if value < que_rec['comment_minimum_float'] or value > que_rec['comment_maximum_float']:
1024 elif que_rec['comment_valid_type'] == 'must_be_date':
1025 value = datetime.datetime.strptime(val, "%Y-%m-%d")
1026 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"):
1030 elif que_rec['comment_valid_type'] == 'must_be_email_address':
1032 if re.match("^[a-zA-Z0-9._%-+]+@[a-zA-Z0-9._%-]+.[a-zA-Z]{2,6}$", val) == None:
1035 raise osv.except_osv(_('Error !'), _("'" + que_rec['question'] + "' \n" + tools.ustr(que_rec['comment_valid_err_msg'])))
1037 resp_obj.write(cr, uid, update, {'comment':val,'state': 'done'})
1038 sur_name_read['store_ans'][update].update({key:val})
1039 elif val and key.split('_')[1] == "comment":
1040 resp_obj.write(cr, uid, update, {'comment':val,'state': 'done'})
1041 sur_name_read['store_ans'][update].update({key:val})
1043 elif val and (key.split('_')[1] == "single" or (len(key.split('_')) > 2 and key.split('_')[2] == 'multi')):
1045 if que_rec['validation_type'] == 'must_be_specific_length':
1046 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']:
1048 elif que_rec['validation_type'] in ['must_be_whole_number', 'must_be_decimal_number', 'must_be_date']:
1051 if que_rec['validation_type'] == 'must_be_whole_number':
1053 if value < que_rec['validation_minimum_no'] or value > que_rec['validation_maximum_no']:
1055 elif que_rec['validation_type'] == 'must_be_decimal_number':
1057 if value < que_rec['validation_minimum_float'] or value > que_rec['validation_maximum_float']:
1059 elif que_rec['validation_type'] == 'must_be_date':
1060 value = datetime.datetime.strptime(val, "%Y-%m-%d")
1061 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"):
1063 except Exception ,e:
1065 elif que_rec['validation_type'] == 'must_be_email_address':
1067 if re.match("^[a-zA-Z0-9._%-+]+@[a-zA-Z0-9._%-]+.[a-zA-Z]{2,6}$", val) == None:
1070 raise osv.except_osv(_('Error !'), _("'" + que_rec['question'] + "' \n" + tools.ustr(que_rec['validation_valid_err_msg'])))
1071 if key.split('_')[1] == "single" :
1072 resp_obj.write(cr, uid, update, {'single_text':val,'state': 'done'})
1074 resp_obj.write(cr, uid, update, {'state': 'done'})
1075 ans_create_id = res_ans_obj.create(cr, uid, {'response_id':update, 'answer_id':ans_id_len[1], 'answer' : val})
1076 sur_name_read['store_ans'][update].update({key:val})
1078 elif val and len(key.split('_')) > 2 and key.split('_')[2] == 'numeric':
1079 resp_obj.write(cr, uid, update, {'state': 'done'})
1080 ans_create_id = res_ans_obj.create(cr, uid, {'response_id':update, 'answer_id':ans_id_len[1], 'answer' : val})
1081 sur_name_read['store_ans'][update].update({key:val})
1083 numeric_sum += int(val)
1084 elif val and len(key.split('_')) == 3:
1085 resp_obj.write(cr, uid, update, {'state': 'done'})
1086 if type(val) == type(''):
1087 ans_create_id = res_ans_obj.create(cr, uid, {'response_id':update, 'answer_id':ans_id_len[1], 'answer' : ans_id_len[2], 'value_choice' : val})
1088 sur_name_read['store_ans'][update].update({key:val})
1090 ans_create_id = res_ans_obj.create(cr, uid, {'response_id':update, 'answer_id':ans_id_len[1], 'answer' : ans_id_len[2]})
1091 sur_name_read['store_ans'][update].update({key:True})
1092 matrix_list.append(key.split('_')[0] + '_' + key.split('_')[1])
1094 elif val and len(key.split('_')) == 2:
1095 resp_obj.write(cr, uid, update, {'state': 'done'})
1096 ans_create_id = res_ans_obj.create(cr, uid, {'response_id':update, 'answer_id':ans_id_len[-1], 'answer' : val})
1097 sur_name_read['store_ans'][update].update({key:val})
1099 surv_name_wiz.write(cr, uid, [context['sur_name_id']], {'store_ans':sur_name_read['store_ans']})
1100 for key,val in vals.items():
1101 if val and key.split('_')[1] == "commentcolumn" and key.split('_')[0] == sur_name_read['store_ans'][update]['question_id']:
1102 for res_id in response_list:
1103 if key.split('_')[2] in res_id.split('_')[1]:
1104 a = res_ans_obj.write(cr, uid, [res_id.split('_')[0]], {'comment_field':val})
1105 sur_name_read['store_ans'][update].update({key:val})
1107 if comment_field and comment_value:
1108 raise osv.except_osv(_('Error re !'), _("'" + que_rec['question'] + "' " + tools.ustr(que_rec['make_comment_field_err_msg'])))
1109 if que_rec['type'] == "rating_scale" and que_rec['rating_allow_one_column_require'] and len(selected_value) > len(list(set(selected_value))):
1110 raise osv.except_osv(_('Error re !'), _("'" + que_rec['question'] + "\n you cannot select same answer more than one times'"))
1111 if que_rec['numeric_required_sum'] and numeric_sum > que_rec['numeric_required_sum']:
1112 raise osv.except_osv(_('Error re !'), _("'" + que_rec['question'] + "' " + tools.ustr(que_rec['numeric_required_sum_err_msg'])))
1113 if not select_count:
1114 resp_obj.write(cr, uid, update, {'state': 'skip'})
1115 if que_rec['type'] in ['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['required_type']:
1117 if (que_rec['required_type'] == 'all' and len(list(set(matrix_list))) < len(que_rec['answer_choice_ids'])) or \
1118 (que_rec['required_type'] == 'at least' and len(list(set(matrix_list))) < que_rec['req_ans']) or \
1119 (que_rec['required_type'] == 'at most' and len(list(set(matrix_list))) > que_rec['req_ans']) or \
1120 (que_rec['required_type'] == 'exactly' and len(list(set(matrix_list))) != que_rec['req_ans']) or \
1121 (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'])):
1122 raise osv.except_osv(_('Error !'), _("'" + que_rec['question'] + "' " + tools.ustr(que_rec['req_error_msg'])))
1123 elif (que_rec['required_type'] == 'all' and select_count < len(que_rec['answer_choice_ids'])) or \
1124 (que_rec['required_type'] == 'at least' and select_count < que_rec['req_ans']) or \
1125 (que_rec['required_type'] == 'at most' and select_count > que_rec['req_ans']) or \
1126 (que_rec['required_type'] == 'exactly' and select_count != que_rec['req_ans']) or \
1127 (que_rec['required_type'] == 'a range' and (select_count < que_rec['minimum_req_ans'] or select_count > que_rec['maximum_req_ans'])):
1128 raise osv.except_osv(_('Error !'), _("'" + que_rec['question'] + "' " + tools.ustr(que_rec['req_error_msg'])))
1129 if que_rec['type'] in ['multiple_choice_only_one_ans','single_textbox','comment'] and que_rec['is_require_answer'] and select_count <= 0:
1130 raise osv.except_osv(_('Error re !'), _("'" + que_rec['question'] + "' " + tools.ustr(que_rec['req_error_msg'])))
1133 def action_next(self, cr, uid, ids, context=None):
1134 surv_name_wiz = self.pool.get('survey.name.wiz')
1135 search_obj = self.pool.get('ir.ui.view')
1136 search_id = search_obj.search(cr,uid,[('model','=','survey.question.wiz'),('name','=','Survey Search')])
1137 surv_name_wiz.write(cr, uid, [context['sur_name_id']], {'transfer':True, 'page':'next'})
1139 'view_type': 'form',
1140 "view_mode": 'form',
1141 'res_model': 'survey.question.wiz',
1142 'type': 'ir.actions.act_window',
1144 'search_view_id':search_id[0],
1148 def action_previous(self, cr, uid, ids, context=None):
1149 surv_name_wiz = self.pool.get('survey.name.wiz')
1150 search_obj = self.pool.get('ir.ui.view')
1151 search_id = search_obj.search(cr,uid,[('model','=','survey.question.wiz'),('name','=','Survey Search')])
1152 surv_name_wiz.write(cr, uid, [context['sur_name_id']], {'transfer':True, 'page':'previous'})
1154 'view_type': 'form',
1155 "view_mode": 'form',
1156 'res_model': 'survey.question.wiz',
1157 'type': 'ir.actions.act_window',
1159 'search_view_id':search_id[0],
1162 survey_question_wiz()
1164 class res_users(osv.osv):
1165 _inherit = "res.users"
1168 'survey_id': fields.many2many('survey', 'survey_users_rel', 'uid', 'sid', 'Groups'),
1172 class survey_request(osv.osv):
1173 _name = "survey.request"
1174 _order = 'date_deadline'
1176 'date_deadline' : fields.date("Deadline date"),
1177 'user_id' : fields.many2one("res.users", "User"),
1178 'email' : fields.char("E-mail", size=64),
1179 'survey_id' : fields.many2one("survey", "Survey", required=1),
1180 'answer_ids' : fields.one2many('survey.answer', 'question_id', 'Answer'),
1181 'state' : fields.selection([('waitin_answer', 'Wating Answer'),('done', 'Done'),('cancelled', 'Cancelled')], 'State')
1185 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: