[IMP]:survey,hr_evaluation,crm_hr--(Ref-YSA,APA)
[odoo/odoo.git] / addons / survey / survey.py
1 # -*- encoding: utf-8 -*-
2 ##############################################################################
3 #
4 #    OpenERP, Open Source Management Solution
5 #    Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>). All Rights Reserved
6 #    $Id$
7 #
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.
12 #
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.
17 #
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/>.
20 #
21 ##############################################################################
22
23 from osv import fields, osv
24 import datetime
25 from time import strftime
26 import datetime
27 import copy
28 from tools.translate import _
29 from lxml import etree
30 from tools import to_xml
31 import tools
32 from mx.DateTime import *
33 import netsvc
34
35 class survey_type(osv.osv):
36     _name = 'survey.type'
37     _description = 'Survey Type'
38     _columns = {
39         'name' : fields.char("Name", size=128, required=1),
40         'code' : fields.char("Code", size=64),
41     }
42 survey_type()
43
44 class survey(osv.osv):
45     _name = 'survey'
46     _description = 'Survey'
47     _rec_name = 'title'
48
49     def default_get(self, cr, uid, fields, context={}):
50         data = super(survey, self).default_get(cr, uid, fields, context)
51         data['responsible_id'] = uid
52         return data
53
54     _columns = {
55         'title' : fields.char('Survey Title', size=128, required=1),
56         'page_ids' : fields.one2many('survey.page', 'survey_id', 'Page'),
57         'date_open' : fields.datetime('Survey Open Date', readonly=1),
58         'date_close' : fields.datetime('Survey Close Date', readonly=1),
59         'max_response_limit' : fields.integer('Maximum Response Limit'),
60         'response_user' : fields.integer('Maximum Response per User',
61                      help="Set to one if  you require only one response per user"),
62         'state' : fields.selection([('draft', 'Draft'), ('open', 'Open'), ('close', 'Closed'), ('cancel', 'Cancelled')], 'Status', readonly=True),
63         'responsible_id' : fields.many2one('res.users', 'Responsible'),
64         'tot_start_survey' : fields.integer("Total Started Survey", readonly=1),
65         'tot_comp_survey' : fields.integer("Total Completed Survey", readonly=1),
66         'note' : fields.text('Description', size=128),
67         'history' : fields.one2many('survey.history', 'survey_id', 'History Lines', readonly=True),
68         'users': fields.many2many('res.users', 'survey_users_rel', 'sid', 'uid', 'Users'),
69         'send_response' : fields.boolean('E-mail Notification on Response'),
70         'type' : fields.many2one('survey.type', 'Type')
71     }
72     _defaults = {
73         'state' : lambda * a: "draft",
74         'tot_start_survey' : lambda * a: 0,
75         'tot_comp_survey' : lambda * a: 0,
76         'send_response' : lambda * a: 1,
77         'response_user' : lambda * a:1,
78     }
79
80     def survey_draft(self, cr, uid, ids, arg):
81         self.write(cr, uid, ids, { 'state' : 'draft'})
82         return True
83
84     def survey_open(self, cr, uid, ids, arg):
85         self.write(cr, uid, ids, { 'state' : 'open', 'date_open':strftime("%Y-%m-%d %H:%M:%S")})
86         return True
87
88     def survey_close(self, cr, uid, ids, arg):
89         self.write(cr, uid, ids, { 'state' : 'close', 'date_close':strftime("%Y-%m-%d %H:%M:%S") })
90         return True
91
92     def survey_cancel(self, cr, uid, ids, arg):
93         self.write(cr, uid, ids, { 'state' : 'cancel' })
94         return True
95
96 survey()
97
98 class survey_history(osv.osv):
99     _name = 'survey.history'
100     _description = 'Survey History'
101     _rec_name = 'date'
102     _columns = {
103         'survey_id' : fields.many2one('survey', 'Survey'),
104         'user_id' : fields.many2one('res.users', 'User', readonly=True),
105         'date' : fields.datetime('Date started', readonly=1),
106     }
107     _defaults = {
108          'date' : lambda * a: datetime.datetime.now()
109     }
110
111 survey_history()
112
113 class survey_page(osv.osv):
114     _name = 'survey.page'
115     _description = 'Survey Pages'
116     _rec_name = 'title'
117     _order = 'sequence'
118     _columns = {
119         'title' : fields.char('Page Title', size=128, required=1),
120         'survey_id' : fields.many2one('survey', 'Survey', ondelete='cascade'),
121         'question_ids' : fields.one2many('survey.question', 'page_id', 'Question'),
122         'sequence' : fields.integer('Page Nr'),
123         'note' : fields.text('Description'),
124     }
125     _defaults = {
126         'sequence' : lambda * a: 1
127     }
128
129     def default_get(self, cr, uid, fields, context={}):
130         data = super(survey_page, self).default_get(cr, uid, fields, context)
131         if context.has_key('line_order') and context['line_order']:
132             if len(context['line_order'][-1]) > 2 and context['line_order'][-1][2].has_key('sequence'):
133                 data['sequence'] = context['line_order'][-1][2]['sequence'] + 1
134         if context.has_key('survey_id'):
135             data['survey_id'] = context['survey_id']
136         return data
137
138     def survey_save(self, cr, uid, ids, context):
139         search_obj = self.pool.get('ir.ui.view')
140         search_id = search_obj.search(cr,uid,[('model','=','survey.question.wiz'),('name','=','Survey Search')])
141         surv_name_wiz = self.pool.get('survey.name.wiz')
142         surv_name_wiz.write(cr, uid, [context['sur_name_id']], {'transfer':True, 'page_no' : context['page_number'] })
143         return {
144                 'view_type': 'form',
145                 "view_mode": 'form',
146                 'res_model': 'survey.question.wiz',
147                 'type': 'ir.actions.act_window',
148                 'target': 'new',
149                 'search_view_id':search_id[0],
150                 'context': context
151                 }
152
153 survey_page()
154
155 class survey_question(osv.osv):
156     _name = 'survey.question'
157     _description = 'Survey Question'
158     _rec_name = 'question'
159     _order = 'sequence'
160
161     def _calc_response(self, cr, uid, ids, field_name, arg, context):
162         if len(ids) == 0:
163             return {}
164         val = {}
165         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))))
166         ids1 = copy.deepcopy(ids)
167         for rec in  cr.fetchall():
168             ids1.remove(rec[0])
169             val[rec[0]] = int(rec[1])
170         for id in ids1:
171             val[id] = 0
172         return val
173
174     _columns = {
175         'page_id' : fields.many2one('survey.page', 'Survey Page', ondelete='cascade', required=1),
176         'question' :  fields.char('Question', size=128, required=1),
177         'answer_choice_ids' : fields.one2many('survey.answer', 'question_id', 'Answer'),
178         'response_ids' : fields.one2many('survey.response.line', 'question_id', 'Response', readonly=1),
179         'is_require_answer' : fields.boolean('Require Answer to Question (optional)'),
180         'required_type' : fields.selection([('all','All'), ('at least','At Least'), ('at most','At Most'), ('exactly','Exactly'), ('a range','A Range')], 'Respondent must answer'),
181         'req_ans' : fields.integer('#Required Answer'),
182         'maximum_req_ans' : fields.integer('Maximum Required Answer'),
183         'minimum_req_ans' : fields.integer('Minimum Required Answer'),
184         'req_error_msg' : fields.text('Error Message'),
185         'allow_comment' : fields.boolean('Allow Comment Field'),
186         'sequence' : fields.integer('Sequence'),
187         'tot_resp' : fields.function(_calc_response, method=True, string="Total Response"),
188         'survey' : fields.related('page_id', 'survey_id', type='many2one', relation='survey', string='Survey'),
189         'descriptive_text' : fields.text('Descriptive Text', size=255),
190         'column_heading_ids' : fields.one2many('survey.question.column.heading', 'question_id',' Column heading'),
191         'type' : fields.selection([('multiple_choice_only_one_ans','Multiple Choice (Only One Answer)'),
192                                      ('multiple_choice_multiple_ans','Multiple Choice (Multiple Answer)'),
193                                      ('matrix_of_choices_only_one_ans','Matrix of Choices (Only One Answers Per Row)'),
194                                      ('matrix_of_choices_only_multi_ans','Matrix of Choices (Multiple Answers Per Row)'),
195                                      ('matrix_of_drop_down_menus','Matrix of Drop-down Menus'),
196                                      ('rating_scale','Rating Scale'),('single_textbox','Single Textbox'),
197                                      ('multiple_textboxes','Multiple Textboxes'),
198                                      ('multiple_textboxes_diff_type','Multiple Textboxes With Different Type'),
199                                      ('comment','Comment/Essay Box'),
200                                      ('numerical_textboxes','Numerical Textboxes'),('date','Date'),
201                                      ('date_and_time','Date and Time'),('descriptive_text','Descriptive Text'),
202                                      ('table','Table'),
203                                     ], 'Question Type',  required=1,),
204         'is_comment_require' : fields.boolean('Add Comment Field (optional)'),
205         'comment_label' : fields.char('Field Label', size = 255),
206         'comment_field_type' : fields.selection([('char', 'Single Line Of Text'), ('text', 'Paragraph of Text')], 'Comment Field Type'),
207         'comment_valid_type' : fields.selection([('do_not_validate', '''Don't Validate Comment Text.'''),
208                                                  ('must_be_specific_length', 'Must Be Specific Length'),
209                                                  ('must_be_whole_number', 'Must Be A Whole Number'),
210                                                  ('must_be_decimal_number', 'Must Be A Decimal Number'),
211                                                  ('must_be_date', 'Must Be A Date'),
212                                                  ('must_be_email_address', 'Must Be An Email Address'),
213                                                  ], 'Text Validation'),
214         'comment_minimum_no' : fields.integer('Minimum number'),
215         'comment_maximum_no' : fields.integer('Maximum number'),
216         'comment_minimum_float' : fields.float('Minimum decimal number'),
217         'comment_maximum_float' : fields.float('Maximum decimal number'),
218         'comment_minimum_date' : fields.date('Minimum date'),
219         'comment_maximum_date' : fields.date('Maximum date'),
220         'comment_valid_err_msg' : fields.text('Error message'),
221         'make_comment_field' : fields.boolean('Make Comment Field an Answer Choice'),
222         'make_comment_field_err_msg' : fields.text('Error message'),
223         'is_validation_require' : fields.boolean('Validate Text (optional)'),
224         'validation_type' : fields.selection([('do_not_validate', '''Don't Validate Comment Text.'''),\
225                                                  ('must_be_specific_length', 'Must Be Specific Length'),\
226                                                  ('must_be_whole_number', 'Must Be A Whole Number'),\
227                                                  ('must_be_decimal_number', 'Must Be A Decimal Number'),\
228                                                  ('must_be_date', 'Must Be A Date'),\
229                                                  ('must_be_email_address', 'Must Be An Email Address')\
230                                                  ], 'Text Validation'),
231         'validation_minimum_no' : fields.integer('Minimum number'),
232         'validation_maximum_no' : fields.integer('Maximum number'),
233         'validation_minimum_float' : fields.float('Minimum decimal number'),
234         'validation_maximum_float' : fields.float('Maximum decimal number'),
235         'validation_minimum_date' : fields.date('Minimum date'),
236         'validation_maximum_date' : fields.date('Maximum date'),
237         'validation_valid_err_msg' : fields.text('Error message'),
238         'numeric_required_sum' : fields.integer('Sum of all choices'),
239         'numeric_required_sum_err_msg' : fields.text('Error message'),
240         'rating_allow_one_column_require' : fields.boolean('Allow Only One Response per Column (Forced Ranking)'),
241         'in_visible_rating_weight':fields.boolean('Is Rating Scale Invisible?'),
242         'in_visible_menu_choice':fields.boolean('Is Menu Choice Invisible?'),
243         'in_visible_answer_type':fields.boolean('Is Answer Type Invisible?'),
244         'comment_column':fields.boolean('Add comment column in matrix'),
245         'column_name':fields.char('Column Name',size=256),
246         'no_of_rows' : fields.integer('No of Rows'),
247     }
248     _defaults = {
249          'sequence' : lambda * a: 1,
250          'type' : lambda * a: 'multiple_choice_multiple_ans',
251          'req_error_msg' : lambda * a: 'This question requires an answer.',
252          'required_type' : lambda * a: 'at least',
253          'req_ans' : lambda * a: 1,
254          'comment_field_type' : lambda * a: 'char',
255          'comment_label' : lambda * a: 'Other (please specify)',
256          'comment_valid_type' : lambda * a: 'do_not_validate',
257          'comment_valid_err_msg' : lambda * a : 'The comment you entered is in an invalid format.',
258          'validation_type' : lambda * a: 'do_not_validate',
259          'validation_valid_err_msg' : lambda * a : 'The comment you entered is in an invalid format.',
260          'numeric_required_sum_err_msg' : lambda * a :'The choices need to add up to [enter sum here].',
261          'make_comment_field_err_msg' : lambda * a : 'Please enter a comment.',
262          'in_visible_answer_type' : lambda * a: 1
263     }
264
265     def on_change_type(self, cr, uid, ids, type, context=None):
266         print ":A:::::::::::::::::::::::::",type
267         if type in ['multiple_textboxes_diff_type']:
268             return {'value': {'in_visible_answer_type':False}}
269         if type in ['rating_scale']:
270             return {'value': {'in_visible_rating_weight':False,'in_visible_menu_choice':True}}
271         elif type in ['matrix_of_drop_down_menus']:
272             return {'value': {'in_visible_rating_weight':True,'in_visible_menu_choice':False}}
273         elif type in ['single_textbox']:
274             return {'value': {'in_visible_rating_weight':True,'in_visible_menu_choice':True}}
275         else:
276             return {'value': {'in_visible_rating_weight':True,'in_visible_menu_choice':True,'in_visible_answer_type':True}}
277
278     def write(self, cr, uid, ids, vals, context=None):
279         questions = self.read(cr,uid, ids, ['answer_choice_ids', 'type', 'required_type','req_ans', 'minimum_req_ans', 'maximum_req_ans', 'column_heading_ids'])
280         for question in questions:
281             col_len = len(question['column_heading_ids'])
282             if vals.has_key('column_heading_ids'):
283                 for col in vals['column_heading_ids']:
284                     if type(col[2]) == type({}):
285                         col_len += 1
286                     else:
287                         col_len -= 1
288             if vals.has_key('type'):
289                 que_type = vals['type']
290             else:
291                 que_type = question['type']
292             if que_type in ['matrix_of_choices_only_one_ans', 'matrix_of_choices_only_multi_ans', 'matrix_of_drop_down_menus', 'rating_scale']:
293                 if not col_len:
294                     raise osv.except_osv(_('Error !'),_("You must enter one or more column heading."))
295             ans_len = len(question['answer_choice_ids'])
296             if vals.has_key('answer_choice_ids'):
297                 for ans in vals['answer_choice_ids']:
298                     if type(ans[2]) == type({}):
299                         ans_len += 1
300                     else:
301                         ans_len -= 1
302             if que_type not in ['descriptive_text', 'single_textbox', 'comment','table']:
303                 if not ans_len:
304                     raise osv.except_osv(_('Error !'),_("You must enter one or more Answer."))
305             req_type = ""
306             if vals.has_key('required_type'):
307                 req_type = vals['required_type']
308             else:
309                 req_type = question['required_type']
310             if que_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']:
311                 if req_type in ['at least', 'at most', 'exactly']:
312                     if vals.has_key('req_ans'):
313                         if not vals['req_ans'] or  vals['req_ans'] > ans_len:
314                             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))
315                     else:
316                         if not question['req_ans'] or  question['req_ans'] > ans_len:
317                             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))
318                 if req_type == 'a range':
319                     minimum_ans = 0
320                     maximum_ans = 0
321                     if vals.has_key('minimum_req_ans'):
322                         minimum_ans = vals['minimum_req_ans']
323                         if not vals['minimum_req_ans'] or  vals['minimum_req_ans'] > ans_len:
324                             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))
325                     else:
326                         minimum_ans = question['minimum_req_ans']
327                         if not question['minimum_req_ans'] or  question['minimum_req_ans'] > ans_len:
328                             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))
329                     if vals.has_key('maximum_req_ans'):
330                         maximum_ans = vals['maximum_req_ans']
331                         if not vals['maximum_req_ans'] or vals['maximum_req_ans'] > ans_len:
332                             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))
333                     else:
334                         maximum_ans = question['maximum_req_ans']
335                         if not question['maximum_req_ans'] or question['maximum_req_ans'] > ans_len:
336                             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))
337                     if maximum_ans <= minimum_ans:
338                         raise osv.except_osv(_('Error !'),_("Maximum Required Answer is greater than Minimum Required Answer"))
339             if question['type'] ==  'matrix_of_drop_down_menus' and vals.has_key('column_heading_ids'):
340                 for col in vals['column_heading_ids']:
341                     if not col[2] or not col[2].has_key('menu_choice') or not col[2]['menu_choice']:
342                         raise osv.except_osv(_('Error !'),_("You must enter one or more menu choices in column heading"))
343                     elif not col[2] or not col[2].has_key('menu_choice') or col[2]['menu_choice'].strip() == '':
344                         raise osv.except_osv(_('Error !'),_("You must enter one or more menu choices in column heading (white spaces not allowed)"))
345         return super(survey_question, self).write(cr, uid, ids, vals, context=context)
346
347     def create(self, cr, uid, vals, context):
348         minimum_ans = 0
349         maximum_ans = 0
350         if vals.has_key('answer_choice_ids') and  not len(vals['answer_choice_ids']):
351             if vals.has_key('type') and vals['type'] not in ['descriptive_text', 'single_textbox', 'comment','table']:
352                 raise osv.except_osv(_('Error !'),_("You must enter one or more answer."))
353         if vals.has_key('column_heading_ids') and  not len(vals['column_heading_ids']):
354             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']:
355                 raise osv.except_osv(_('Error !'),_("You must enter one or more column heading."))
356         if vals['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']:
357             if vals.has_key('is_require_answer') and vals.has_key('required_type') and vals['required_type'] in ['at least', 'at most', 'exactly']:
358                 if vals['req_ans'] > len(vals['answer_choice_ids']) or not vals['req_ans']:
359                     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))
360             if vals.has_key('is_require_answer') and vals.has_key('required_type') and vals['required_type'] == 'a range':
361                 minimum_ans = vals['minimum_req_ans']
362                 maximum_ans = vals['maximum_req_ans']
363                 if vals['minimum_req_ans'] > len(vals['answer_choice_ids']) or not vals['minimum_req_ans']:
364                     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))
365                 if vals['maximum_req_ans'] > len(vals['answer_choice_ids']) or not vals['maximum_req_ans']:
366                     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))
367                 if maximum_ans <= minimum_ans:
368                     raise osv.except_osv(_('Error !'),_("Maximum Required Answer is greater than Minimum Required Answer"))
369         if vals['type'] ==  'matrix_of_drop_down_menus':
370             for col in vals['column_heading_ids']:
371                 if not col[2] or not col[2].has_key('menu_choice') or not col[2]['menu_choice']:
372                     raise osv.except_osv(_('Error !'),_("You must enter one or more menu choices in column heading"))
373                 elif not col[2] or not col[2].has_key('menu_choice') or col[2]['menu_choice'].strip() == '':
374                     raise osv.except_osv(_('Error !'),_("You must enter one or more menu choices in column heading (white spaces not allowed)"))
375         res = super(survey_question, self).create(cr, uid, vals, context)
376         return res
377
378     def survey_save(self, cr, uid, ids, context):
379         search_obj = self.pool.get('ir.ui.view')
380         search_id = search_obj.search(cr,uid,[('model','=','survey.question.wiz'),('name','=','Survey Search')])
381         surv_name_wiz = self.pool.get('survey.name.wiz')
382         surv_name_wiz.write(cr, uid, [context['sur_name_id']], {'transfer':True, 'page_no' : context['page_number'] })
383         return {
384                 'view_type': 'form',
385                 "view_mode": 'form',
386                 'res_model': 'survey.question.wiz',
387                 'type': 'ir.actions.act_window',
388                 'target': 'new',
389                 'search_view_id':search_id[0],
390                 'context': context
391                 }
392
393     def default_get(self, cr, uid, fields, context={}):
394         data = super(survey_question, self).default_get(cr, uid, fields, context)
395         if context.has_key('line_order') and context['line_order']:
396             if len(context['line_order'][-1]) > 2 and context['line_order'][-1][2].has_key('sequence'):
397                 data['sequence'] = context['line_order'][-1][2]['sequence'] + 1
398         if context.has_key('page_id'):
399             data['page_id']= context['page_id']
400         return data
401
402 survey_question()
403
404
405 class survey_question_column_heading(osv.osv):
406     _name = 'survey.question.column.heading'
407     _description = 'Survey Question Column Heading'
408     _rec_name = 'title'
409
410     def _get_in_visible_rating_weight(self,cr, uid, context={}):
411         if context.get('in_visible_rating_weight',False):
412             return context['in_visible_rating_weight']
413         return False
414     def _get_in_visible_menu_choice(self,cr, uid, context={}):
415         if context.get('in_visible_menu_choice',False):
416             return context['in_visible_menu_choice']
417         return False
418
419     _columns = {
420         'title' : fields.char('Column Heading', size=128, required=1),
421         'menu_choice' : fields.text('Menu Choice'),
422         'rating_weight' : fields.integer('Weight'),
423         'question_id' : fields.many2one('survey.question', 'Question', ondelete='cascade'),
424         'in_visible_rating_weight':fields.boolean('Is Rating Scale Invisible ??'),
425         'in_visible_menu_choice':fields.boolean('Is Menu Choice Invisible??')
426     }
427     _defaults={
428        'in_visible_rating_weight':_get_in_visible_rating_weight,
429        'in_visible_menu_choice':_get_in_visible_menu_choice,
430     }
431
432 survey_question_column_heading()
433
434 class survey_answer(osv.osv):
435     _name = 'survey.answer'
436     _description = 'Survey Answer'
437     _rec_name = 'answer'
438     _order = 'sequence'
439
440     def _calc_response_avg(self, cr, uid, ids, field_name, arg, context):
441         val = {}
442         for rec in self.browse(cr, uid, ids):
443             cr.execute("select count(question_id) ,(select count(answer_id) \
444                 from survey_response_answer sra, survey_response_line sa \
445                 where sra.response_id = sa.id and sra.answer_id = %d \
446                 and sa.state='done') as tot_ans from survey_response_line \
447                 where question_id = %d and state = 'done'"\
448                      % (rec.id, rec.question_id.id))
449             res = cr.fetchone()
450             if res[0]:
451                 avg = float(res[1]) * 100 / res[0]
452             else:
453                 avg = 0.0
454             val[rec.id] = {
455                 'response': res[1],
456                 'average': round(avg, 2),
457             }
458         return val
459
460     def _get_in_visible_answer_type(self,cr, uid, context={}):
461         if context.get('in_visible_answer_type',False):
462             return context['in_visible_answer_type']
463         return False
464     
465     _columns = {
466         'question_id' : fields.many2one('survey.question', 'Question', ondelete='cascade'),
467         'answer' : fields.char('Answer', size=128, required=1),
468         'sequence' : fields.integer('Sequence'),
469         'response' : fields.function(_calc_response_avg, method=True, string="#Response", multi='sums'),
470         'average' : fields.function(_calc_response_avg, method=True, string="#Avg", multi='sums'),
471         'type' : fields.selection([('char','Character'),('date','Date'),('datetime','Date & Time'),('integer','Integer'),('float','Float')], "Type of Answer",required=1),
472         'in_visible_answer_type':fields.boolean('Is Answer Type Invisible??')
473     }
474     _defaults = {
475          'sequence' : lambda * a: 1,
476          'type' : lambda * a: 'char',
477          'in_visible_answer_type':_get_in_visible_answer_type,
478     }
479
480     def default_get(self, cr, uid, fields, context={}):
481         data = super(survey_answer, self).default_get(cr, uid, fields, context)
482         if context.has_key('line_order') and context['line_order']:
483             if len(context['line_order'][-1]) > 2 and context['line_order'][-1][2].has_key('sequence'):
484                 data['sequence'] = context['line_order'][-1][2]['sequence'] + 1
485         return data
486
487 survey_answer()
488
489 class survey_response(osv.osv):
490     _name = "survey.response"
491     _rec_name = 'date_create'
492     _columns = {
493         'survey_id' : fields.many2one('survey', 'Survey', required=1, ondelete='cascade'),
494         'date_create' : fields.datetime('Create Date', required=1),
495         'user_id' : fields.many2one('res.users', 'User'),
496         'response_type' : fields.selection([('manually', 'Manually'), ('link', 'Link')], 'Response Type', required=1),
497         'question_ids' : fields.one2many('survey.response.line', 'response_id', 'Response Answer'),
498         'state' : fields.selection([('done', 'Finished '),('skip', 'Not Finished')], 'Status', readonly=True),
499     }
500     _defaults = {
501         'state' : lambda * a: "skip",
502     }
503
504 survey_response()
505
506 class survey_response_line(osv.osv):
507     _name = 'survey.response.line'
508     _description = 'Survey Response Line'
509     _rec_name = 'date_create'
510     _columns = {
511         'response_id' : fields.many2one('survey.response', 'Response', ondelete='cascade'),
512         'date_create' : fields.datetime('Create Date', required=1),
513         'state' : fields.selection([('draft', 'Draft'), ('done', 'Answered'),('skip', 'Skiped')], 'Status', readonly=True),
514         'question_id' : fields.many2one('survey.question', 'Question'),
515         'page_id' : fields.related('question_id', 'page_id', type='many2one', relation='survey.page', string='Page'),
516         'response_answer_ids' : fields.one2many('survey.response.answer', 'response_id', 'Response Answer'),
517         'response_table_ids' : fields.one2many('survey.tbl.column.heading', 'response_table_id', 'Response Answer'),
518         'comment' : fields.text('Notes'),
519         'single_text' : fields.char('Text', size=255),
520     }
521     _defaults = {
522         'state' : lambda * a: "draft",
523     }
524
525     def response_draft(self, cr, uid, ids, arg):
526         self.write(cr, uid, ids, { 'state' : 'draft' })
527         return True
528
529     def response_done(self, cr, uid, ids, arg):
530         self.write(cr, uid, ids, { 'state' : 'done' })
531         return True
532
533     def response_skip(self, cr, uid, ids, arg):
534         self.write(cr, uid, ids, { 'state' : 'skip' })
535         return True
536
537 survey_response_line()
538
539 class survey_tbl_column_heading(osv.osv):
540     _name = 'survey.tbl.column.heading'
541     _order = 'name'
542     _columns = {
543         'name' : fields.integer('Row Number'),
544         'column_id' : fields.many2one('survey.question.column.heading', 'Column'),
545         'value' : fields.char('Value', size = 255),
546         'response_table_id' : fields.many2one('survey.response.line', 'Response', ondelete='cascade'),
547     }
548
549 survey_tbl_column_heading()
550
551 class survey_response_answer(osv.osv):
552     _name = 'survey.response.answer'
553     _description = 'Survey Response Answer'
554     _rec_name = 'response_id'
555     _columns = {
556         'response_id' : fields.many2one('survey.response.line', 'Response', ondelete='cascade'),
557         'answer_id' : fields.many2one('survey.answer', 'Answer', required=1),
558         'column_id' : fields.many2one('survey.question.column.heading','Column'),
559         'answer' : fields.char('Value', size =255),
560         'value_choice' : fields.char('Value Choice', size =255),
561         'comment' : fields.text('Notes'),
562         'comment_field' : fields.char('Comment', size = 255)
563     }
564
565 survey_response_answer()
566
567 class survey_name_wiz(osv.osv_memory):
568     _name = 'survey.name.wiz'
569
570     def default_get(self, cr, uid, fields, context={}):
571         data = super(survey_name_wiz, self).default_get(cr, uid, fields, context)
572         if context.has_key('survey_id'):
573             data['survey_id'] = context['survey_id']
574         return data
575
576     def _get_survey(self, cr, uid, context=None):
577         surv_obj = self.pool.get("survey")
578         result = []
579         if context.has_key('survey_id'):
580             for sur in surv_obj.browse(cr, uid, [context['survey_id']]):
581                 result.append((sur.id, sur.title))
582             return result
583         group_id = self.pool.get('res.groups').search(cr, uid, [('name', '=', 'Survey / Manager')])
584         user_obj = self.pool.get('res.users')
585         user_rec = user_obj.read(cr, uid, uid)
586         for sur in surv_obj.browse(cr, uid, surv_obj.search(cr, uid, [])):
587             if sur.state == 'open':
588                 if group_id[0]  in user_rec['groups_id']:
589                     result.append((sur.id, sur.title))
590                 elif sur.id in user_rec['survey_id']:
591                     result.append((sur.id, sur.title))
592         return result
593
594     _columns = {
595         'survey_id': fields.selection(_get_survey, "Survey", required="1"),
596         'page_no' : fields.integer('Page Number'),
597         'note' : fields.text("Description"),
598         'page' : fields.char('Page Position',size = 12),
599         'transfer' : fields.boolean('Page Transfer'),
600         'store_ans' : fields.text('Store Answer'),
601         'response' : fields.char('Response',size=16)
602     }
603     _defaults = {
604         'page_no' : lambda * a: - 1,
605         'page' : lambda * a: 'next',
606         'transfer' : lambda * a: 1,
607         'response' : lambda * a: 0,
608     }
609
610     def action_next(self, cr, uid, ids, context=None):
611         sur_id = self.read(cr, uid, ids, [])[0]
612         survey_id = sur_id['survey_id']
613         context.update({'survey_id' : survey_id, 'sur_name_id' : sur_id['id']})
614         if not context.has_key('active'):
615             cr.execute('select count(id) from survey_history where user_id=%s\
616                         and survey_id=%s' % (uid,survey_id))
617             res = cr.fetchone()[0]
618             user_limit = self.pool.get('survey').read(cr, uid, survey_id, ['response_user'])['response_user']
619             if user_limit and res >= user_limit:
620                 raise osv.except_osv(_('Warning !'),_("You can not give response for this survey more than %s times") % (user_limit))
621             his_id = self.pool.get('survey.history').create(cr, uid, {'user_id': uid, \
622                                               'date': strftime('%Y-%m-%d %H:%M:%S'), 'survey_id': survey_id})
623             survey_obj = self.pool.get('survey')
624             sur_rec = survey_obj.read(cr,uid,self.read(cr,uid,ids)[0]['survey_id'])
625             if sur_rec['max_response_limit'] and sur_rec['max_response_limit'] <= sur_rec['tot_start_survey']:
626                 raise osv.except_osv(_('Warning !'),_("You can not give more response. Please contact the author of this survey for further assistance."))
627             survey_obj.write(cr, uid, survey_id,  {'tot_start_survey' : sur_rec['tot_start_survey'] + 1})
628         search_obj = self.pool.get('ir.ui.view')
629         search_id = search_obj.search(cr,uid,[('model','=','survey.question.wiz'),('name','=','Survey Search')])
630         return {
631             'view_type': 'form',
632             "view_mode": 'form',
633             'res_model': 'survey.question.wiz',
634             'type': 'ir.actions.act_window',
635             'target': 'new',
636             'search_view_id':search_id[0],
637             'context' : context
638          }
639
640     def on_change_survey(self, cr, uid, ids, survey_id, context=None):
641         notes = self.pool.get('survey').read(cr, uid, survey_id, ['note'])['note']
642         return {'value': {'note' : notes}}
643
644 survey_name_wiz()
645
646 class survey_question_wiz(osv.osv_memory):
647     _name = 'survey.question.wiz'
648     _columns = {
649         'name': fields.integer('Number'),
650     }
651
652     def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False,submenu=False):
653         result = super(survey_question_wiz, self).fields_view_get(cr, uid, view_id, view_type, context, toolbar,submenu)
654         surv_name_wiz = self.pool.get('survey.name.wiz')
655         if view_type in ['form']:
656             sur_name_rec = surv_name_wiz.read(cr, uid, context['sur_name_id'])
657             survey_id = context['survey_id']
658             survey_obj = self.pool.get('survey')
659             sur_rec = survey_obj.read(cr, uid, survey_id, [])
660             page_obj = self.pool.get('survey.page')
661             que_obj = self.pool.get('survey.question')
662             ans_obj = self.pool.get('survey.answer')
663             response_obj = self.pool.get('survey.response.line')
664             que_col_head = self.pool.get('survey.question.column.heading')
665             p_id = sur_rec['page_ids']
666             total_pages = len(p_id)
667             pre_button = False
668             if not sur_name_rec['page_no'] + 1 :
669                 surv_name_wiz.write(cr, uid, [context['sur_name_id']], {'store_ans':{}})
670             sur_name_read = surv_name_wiz.read(cr, uid, context['sur_name_id'])
671             page_number = int(sur_name_rec['page_no'])
672             if sur_name_read['transfer'] or not sur_name_rec['page_no'] + 1:
673                 surv_name_wiz.write(cr, uid, [context['sur_name_id']], {'transfer':False})
674                 flag = False
675                 if sur_name_read['page'] == "next" or sur_name_rec['page_no'] == - 1 :
676                     if len(p_id) > sur_name_rec['page_no'] + 1 :
677                         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:
678                             survey_obj.write(cr, uid, survey_id, {'state':'close', 'date_close':strftime("%Y-%m-%d %H:%M:%S")})
679                         p_id = p_id[sur_name_rec['page_no'] + 1]
680                         surv_name_wiz.write(cr, uid, [context['sur_name_id']], {'page_no' : sur_name_rec['page_no'] + 1})
681                         flag = True
682                         page_number += 1
683                     if sur_name_rec['page_no'] > - 1:
684                         pre_button = True
685                 else:
686                     if sur_name_rec['page_no'] != 0:
687                         p_id = p_id[sur_name_rec['page_no'] - 1]
688                         surv_name_wiz.write(cr, uid, [context['sur_name_id']], {'page_no' : sur_name_rec['page_no'] - 1})
689                         flag = True
690                         page_number -= 1
691                     if sur_name_rec['page_no'] > 1:
692                         pre_button = True
693                 if flag:
694                     fields = {}
695                     pag_rec = page_obj.read(cr, uid, p_id)
696                     xml_form = etree.Element('form', {'string': _(tools.ustr(pag_rec['title']))})
697                     etree.SubElement(xml_form, 'label', {'string': to_xml(tools.ustr(pag_rec['note'] or '')), 'align': '0.0', 'colspan':'4'})
698                     que_ids = pag_rec['question_ids']
699                     qu_no = 0
700                     for que in que_ids:
701                         qu_no += 1
702                         que_rec = que_obj.read(cr, uid, que)
703                         descriptive_text = ""
704                         separator_string = tools.ustr(qu_no) + "." + tools.ustr(que_rec['question'])
705                         if not context.has_key('active') and que_rec['is_require_answer']:
706                             star='*'
707                         else:
708                             star=''
709                         xml_group = etree.SubElement(xml_form, 'group', {'col': '2', 'colspan': '4'})
710                         if context.has_key('active') and context.has_key('edit'):
711                             xml_group = etree.SubElement(xml_form, 'group', {'col': '1', 'colspan': '2'})
712                             etree.SubElement(xml_group, 'separator', {'string': star+to_xml(separator_string), 'colspan': '3'})
713                             xml_group1 = etree.SubElement(xml_form, 'group', {'col': '2', 'colspan': '2'})
714                             context.update({'question_id' : tools.ustr(que),'page_number' : sur_name_rec['page_no'] , 'transfer' : sur_name_read['transfer'], 'page_id' : p_id})
715                             etree.SubElement(xml_group1, 'button', {'string' :'','icon': "gtk-edit", 'type' :'object', 'name':"action_edit_question", 'context' : tools.ustr(context)})
716                             etree.SubElement(xml_group1, 'button', {'string' :'','icon': "gtk-delete", 'type' :'object','name':"action_delete_question", 'context' : tools.ustr(context)})
717                         else:
718                             xml_group = etree.SubElement(xml_form, 'group', {'col': '1', 'colspan': '4'})
719                             etree.SubElement(xml_group, 'separator', {'string': star+to_xml(separator_string), 'colspan': '4'})
720                         ans_ids = ans_obj.read(cr, uid, que_rec['answer_choice_ids'], [])
721                         xml_group = etree.SubElement(xml_form, 'group', {'col': '1', 'colspan': '4'})
722                         if que_rec['type'] == 'multiple_choice_only_one_ans':
723                             selection = []
724                             for ans in ans_ids:
725                                 selection.append((tools.ustr(ans['id']), ans['answer']))
726                             xml_group = etree.SubElement(xml_group, 'group', {'col': '2', 'colspan': '2'})
727                             etree.SubElement(xml_group, 'field', {'name': tools.ustr(que) + "_selection"})
728                             fields[tools.ustr(que) + "_selection"] = {'type':'selection', 'selection' :selection, 'string':"Answer"}
729                         elif que_rec['type'] == 'multiple_choice_multiple_ans':
730                             xml_group = etree.SubElement(xml_group, 'group', {'col': '4', 'colspan': '4'})
731                             for ans in ans_ids:
732                                 etree.SubElement(xml_group, 'field', {'name': tools.ustr(que) + "_" + tools.ustr(ans['id'])})
733                                 fields[tools.ustr(que) + "_" + tools.ustr(ans['id'])] = {'type':'boolean', 'string':ans['answer']}
734                         elif que_rec['type'] in ['matrix_of_choices_only_one_ans', 'rating_scale']:
735                             if que_rec['comment_column']:
736                                 col = "4"
737                                 colspan = "4"
738                             else:
739                                col = "2"
740                                colspan = "2"
741                             xml_group = etree.SubElement(xml_group, 'group', {'col': tools.ustr(col), 'colspan': tools.ustr(colspan)})
742                             for row in ans_ids:
743                                 etree.SubElement(xml_group, 'newline')
744                                 etree.SubElement(xml_group, 'field', {'name': tools.ustr(que) + "_selection_" + tools.ustr(row['id']),'string':to_xml(tools.ustr(row['answer']))})
745                                 selection = [('','')]
746                                 for col in que_col_head.read(cr, uid, que_rec['column_heading_ids']):
747                                     selection.append((col['id'], col['title']))
748                                 fields[tools.ustr(que) + "_selection_" + tools.ustr(row['id'])] = {'type':'selection', 'selection' : selection, 'string': "Answer"}
749                                 if que_rec['comment_column']:
750                                    fields[tools.ustr(que) + "_commentcolumn_"+tools.ustr(row['id']) + "_field"] = {'type':'char', 'size' : 255, 'string':tools.ustr(que_rec['column_name']), 'views':{}}
751                                    etree.SubElement(xml_group, 'field', {'name': tools.ustr(que) + "_commentcolumn_"+tools.ustr(row['id'])+ "_field"})
752                         elif que_rec['type'] == 'matrix_of_choices_only_multi_ans':
753                             xml_group = etree.SubElement(xml_group, 'group', {'col': str(len(que_rec['column_heading_ids']) + 1), 'colspan': '4'})
754                             etree.SubElement(xml_group, 'separator', {'string': '.','colspan': '1'})
755                             for col in que_col_head.read(cr, uid, que_rec['column_heading_ids']):
756                                 etree.SubElement(xml_group, 'separator', {'string': tools.ustr(col['title']),'colspan': '1'})
757                             for row in ans_ids:
758                                 etree.SubElement(xml_group, 'label', {'string': to_xml(tools.ustr(row['answer'])) +' :-', 'align': '0.0'})
759                                 for col in que_col_head.read(cr, uid, que_rec['column_heading_ids']):
760                                     etree.SubElement(xml_group, 'field', {'name': tools.ustr(que) + "_" + tools.ustr(row['id']) + "_" + tools.ustr(col['id']), 'nolabel':"1"})
761                                     fields[tools.ustr(que) + "_" + tools.ustr(row['id'])  + "_" + tools.ustr(col['id'])] = {'type':'boolean', 'string': col['title']}
762                         elif que_rec['type'] == 'matrix_of_drop_down_menus':
763                             xml_group = etree.SubElement(xml_group, 'group', {'col': str(len(que_rec['column_heading_ids']) + 1), 'colspan': '4'})
764                             etree.SubElement(xml_group, 'separator', {'string': '.','colspan': '1'})
765                             for col in que_col_head.read(cr, uid, que_rec['column_heading_ids']):
766                                 etree.SubElement(xml_group, 'separator', {'string': tools.ustr(col['title']),'colspan': '1'})
767                             for row in ans_ids:
768                                 etree.SubElement(xml_group, 'label', {'string': to_xml(tools.ustr(row['answer']))+' :-', 'align': '0.0'})
769                                 for col in que_col_head.read(cr, uid, que_rec['column_heading_ids']):
770                                     selection = []
771                                     if col['menu_choice']:
772                                         for item in col['menu_choice'].split('\n'):
773                                             if item and not item.strip() == '': selection.append((item ,item))
774                                     etree.SubElement(xml_group, 'field', {'name': tools.ustr(que) + "_" + tools.ustr(row['id']) + "_" + tools.ustr(col['id']),'nolabel':'1'})
775                                     fields[tools.ustr(que) + "_" + tools.ustr(row['id'])  + "_" + tools.ustr(col['id'])] = {'type':'selection', 'string': col['title'], 'selection':selection}
776                         elif que_rec['type'] == 'multiple_textboxes':
777                             xml_group = etree.SubElement(xml_group, 'group', {'col': '1', 'colspan': '4'})
778                             type = "char"
779                             if que_rec['is_validation_require']:
780                                 if que_rec['validation_type'] in ['must_be_whole_number']:
781                                     type = "integer"
782                                 elif que_rec['validation_type'] in ['must_be_decimal_number']:
783                                     type = "float"
784                                 elif que_rec['validation_type'] in ['must_be_date']:
785                                     type = "date"
786                             for ans in ans_ids:
787                                 etree.SubElement(xml_group, 'field', {'name': tools.ustr(que) + "_" + tools.ustr(ans['id']) + "_multi"})
788                                 if type == "char" :
789                                     fields[tools.ustr(que) + "_" + tools.ustr(ans['id']) + "_multi"] = {'type':'char', 'size':255, 'string':ans['answer']}
790                                 else:
791                                     fields[tools.ustr(que) + "_" + tools.ustr(ans['id']) + "_multi"] = {'type': str(type), 'string':ans['answer']}
792                         elif que_rec['type'] == 'numerical_textboxes':
793                             xml_group = etree.SubElement(xml_group, 'group', {'col': '2', 'colspan': '2'})
794                             for ans in ans_ids:
795                                 etree.SubElement(xml_group, 'field', {'name': tools.ustr(que) + "_" + tools.ustr(ans['id']) + "_numeric"})
796                                 fields[tools.ustr(que) + "_" + tools.ustr(ans['id']) + "_numeric"] = {'type':'integer', 'string':ans['answer']}
797                         elif que_rec['type'] == 'date':
798                             xml_group = etree.SubElement(xml_group, 'group', {'col': '2', 'colspan': '2'})
799                             for ans in ans_ids:
800                                 etree.SubElement(xml_group, 'field', {'name': tools.ustr(que) + "_" + tools.ustr(ans['id'])})
801                                 fields[tools.ustr(que) + "_" + tools.ustr(ans['id'])] = {'type':'date', 'string':ans['answer']}
802                         elif que_rec['type'] == 'date_and_time':
803                             xml_group = etree.SubElement(xml_group, 'group', {'col': '2', 'colspan': '2'})
804                             for ans in ans_ids:
805                                 etree.SubElement(xml_group, 'field', {'name': tools.ustr(que) + "_" + tools.ustr(ans['id'])})
806                                 fields[tools.ustr(que) + "_" + tools.ustr(ans['id'])] = {'type':'datetime', 'string':ans['answer']}
807                         elif que_rec['type'] == 'descriptive_text':
808                             for que_test in que_rec['descriptive_text'].split('\n'):
809                                 etree.SubElement(xml_group, 'label', {'string': to_xml(tools.ustr(que_test)), 'align':"0.0"})
810                         elif que_rec['type'] == 'single_textbox':
811                             etree.SubElement(xml_group, 'field', {'name': tools.ustr(que) + "_single", 'nolabel':"1" ,'colspan':"4"})
812                             fields[tools.ustr(que) + "_single"] = {'type':'char', 'size' : 255, 'string':"single_textbox", 'views':{}}
813                         elif que_rec['type'] == 'comment':
814                             etree.SubElement(xml_group, 'field', {'name': tools.ustr(que) + "_comment", 'nolabel':"1" ,'colspan':"4"})
815                             fields[tools.ustr(que) + "_comment"] = {'type':'text', 'string':"Comment/Eassy Box", 'views':{}}
816                         elif que_rec['type'] == 'table':
817                             xml_group = etree.SubElement(xml_group, 'group', {'col': str(len(que_rec['column_heading_ids'])), 'colspan': '4'})
818                             for col in que_col_head.read(cr, uid, que_rec['column_heading_ids']):
819                                 etree.SubElement(xml_group, 'separator', {'string': tools.ustr(col['title']),'colspan': '1'})
820                             for row in range(0,que_rec['no_of_rows']):
821                                 for col in que_col_head.read(cr, uid, que_rec['column_heading_ids']):
822                                     etree.SubElement(xml_group, 'field', {'name': tools.ustr(que) + "_table_" + tools.ustr(col['id']) +"_"+ tools.ustr(row), 'nolabel':"1"})
823                                     fields[tools.ustr(que) + "_table_" + tools.ustr(col['id']) +"_"+ tools.ustr(row)] = {'type':'char','size':255,'views':{}}
824                         elif que_rec['type'] == 'multiple_textboxes_diff_type':
825                             xml_group = etree.SubElement(xml_group, 'group', {'col': '1', 'colspan': '4'})
826                             for ans in ans_ids:
827                                 etree.SubElement(xml_group, 'field', {'name': tools.ustr(que) + "_" + tools.ustr(ans['id']) + "_multi"})
828                                 if ans['type'] == "char" :
829                                     fields[tools.ustr(que) + "_" + tools.ustr(ans['id']) + "_multi"] = {'type':'char', 'size':255, 'string':ans['answer']}
830                                 else:
831                                     fields[tools.ustr(que) + "_" + tools.ustr(ans['id']) + "_multi"] = {'type': str(ans['type']), 'string':ans['answer']}
832
833                         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']:
834                             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']:
835                                 etree.SubElement(xml_group, 'field', {'name': tools.ustr(que) + "_otherfield", 'colspan':"4"})
836                                 fields[tools.ustr(que) + "_otherfield"] = {'type':'boolean', 'string':que_rec['comment_label'], 'views':{}}
837                                 if que_rec['comment_field_type'] == 'char':
838                                     etree.SubElement(xml_group, 'field', {'name': tools.ustr(que) + "_other", 'nolabel':"1" ,'colspan':"4"})
839                                     fields[tools.ustr(que) + "_other"] = {'type': 'char', 'string': '', 'size':255, 'views':{}}
840                                 elif que_rec['comment_field_type'] == 'text':
841                                     etree.SubElement(xml_group, 'field', {'name': tools.ustr(que) + "_other", 'nolabel':"1" ,'colspan':"4"})
842                                     fields[tools.ustr(que) + "_other"] = {'type': 'text', 'string': '', 'views':{}}
843                             else:
844                                 if que_rec['comment_field_type'] == 'char':
845                                     etree.SubElement(xml_group, 'label', {'string': to_xml(tools.ustr(que_rec['comment_label'])),'colspan':"4"})
846                                     etree.SubElement(xml_group, 'field', {'name': tools.ustr(que) + "_other", 'nolabel':"1" ,'colspan':"4"})
847                                     fields[tools.ustr(que) + "_other"] = {'type': 'char', 'string': '', 'size':255, 'views':{}}
848                                 elif que_rec['comment_field_type'] == 'text':
849                                     etree.SubElement(xml_group, 'label', {'string': to_xml(tools.ustr(que_rec['comment_label'])),'colspan':"4"})
850                                     etree.SubElement(xml_group, 'field', {'name': tools.ustr(que) + "_other", 'nolabel':"1" ,'colspan':"4"})
851                                     fields[tools.ustr(que) + "_other"] = {'type': 'text', 'string': '', 'views':{}}
852                     etree.SubElement(xml_form, 'separator', {'colspan': '4'})
853                     xml_group = etree.SubElement(xml_form, 'group', {'col': '6', 'colspan': '4'})
854                     etree.SubElement(xml_group, 'field', {'name': 'progress_bar_' + tools.ustr(page_number) , 'widget':'progressbar'})
855                     fields['progress_bar_' + tools.ustr(page_number)] = {'type':'float', 'string':"Progress", 'views':{}}
856                     etree.SubElement(xml_group, 'label', {'string': tools.ustr(page_number+ 1) + "/" + tools.ustr(total_pages)})
857                     etree.SubElement(xml_group, 'button', {'icon': "gtk-cancel", 'special': "cancel",'string':"Cancel"})
858                     if pre_button:
859                         etree.SubElement(xml_group, 'button', {'colspan':"1",'icon':"gtk-go-back",'name':"action_previous",'string':"Previous",'type':"object"})
860                     etree.SubElement(xml_group, 'button', {'icon': "gtk-go-forward", 'name':"action_next",'string':"Next",'type':"object"})
861                     if context.has_key('active') and context.has_key('edit'):
862                         etree.SubElement(xml_form, 'separator', {'string' : '','colspan': '4'})
863                         context.update({'page_id' : tools.ustr(p_id),'page_number' : sur_name_rec['page_no'] , 'transfer' : sur_name_read['transfer']})
864                         xml_group3 = etree.SubElement(xml_form, 'group', {'col': '4', 'colspan': '4'})
865                         etree.SubElement(xml_group3, 'button', {'string' :'Add Page','icon': "gtk-new", 'type' :'object','name':"action_new_page", 'context' : tools.ustr(context)})
866                         etree.SubElement(xml_group3, 'button', {'string' :'Edit Page','icon': "gtk-edit", 'type' :'object','name':"action_edit_page", 'context' : tools.ustr(context)})
867                         etree.SubElement(xml_group3, 'button', {'string' :'Delete Page','icon': "gtk-delete", 'type' :'object','name':"action_delete_page", 'context' : tools.ustr(context)})
868                         etree.SubElement(xml_group3, 'button', {'string' :'Add Question','icon': "gtk-new", 'type' :'object','name':"action_new_question", 'context' : tools.ustr(context)})
869                     root = xml_form.getroottree()
870                     result['arch'] = etree.tostring(root)
871                     result['fields'] = fields
872                     result['context'] = context
873                 else:
874                     if not context.has_key('active'):
875                         survey_obj.write(cr, uid, survey_id, {'tot_comp_survey' : sur_rec['tot_comp_survey'] + 1})
876                         sur_response_obj = self.pool.get('survey.response')
877                         sur_response_obj.write(cr, uid, [sur_name_read['response']], {'state' : 'done'})
878                         if sur_rec['send_response']:
879                             user_obj = self.pool.get('res.users')
880                             survey_data = survey_obj.browse(cr, uid, int(survey_id))
881                             response_id = surv_name_wiz.read(cr,uid,context['sur_name_id'])['response']
882                             context.update({'response_id':response_id})
883                             report = self.create_report(cr, uid, [int(survey_id)], 'report.survey.browse.response', survey_data.title,context)
884                             attachments = []
885                             file = open("/tmp/" + survey_data.title + ".pdf")
886                             file_data = ""
887                             while 1:
888                                 line = file.readline()
889                                 file_data += line
890                                 if not line:
891                                     break
892                             attachments.append((survey_data.title + ".pdf",file_data))
893                             user_email = False
894                             resp_email = False
895                             if user_obj.browse(cr, uid, uid).address_id.id:
896                                 cr.execute("select email from res_partner_address where id =%d" % user_obj.browse(cr, uid, uid).address_id.id)
897                                 user_email = cr.fetchone()[0]
898                             resp_id = survey_data.responsible_id.address_id
899                             if resp_id:
900                                 cr.execute("select email from res_partner_address where id =%d" % resp_id.id)
901                                 resp_email = cr.fetchone()[0]
902                             if user_email and resp_email:
903                                 mail = "Hello " + survey_data.responsible_id.name + ",\n\n " + str(user_obj.browse(cr, uid, uid).name) + " Give Response Of " + survey_data.title + " Survey.\n\n Thanks,"
904                                 tools.email_send(user_email, [resp_email], "Survey Response Of " + str(user_obj.browse(cr, uid, uid).name) , mail, attach = attachments)
905
906                     xml_form = etree.Element('form', {'string': _('Complete Survey Response')})
907                     etree.SubElement(xml_form, 'separator', {'string': 'Complete Survey', 'colspan': "4"})
908                     etree.SubElement(xml_form, 'label', {'string': 'Thanks for your response'})
909                     etree.SubElement(xml_form, 'newline')
910                     etree.SubElement(xml_form, 'button', {'icon': "gtk-go-forward", 'special':"cancel",'string':"OK",'colspan':"2"})
911                     root = xml_form.getroottree()
912                     result['arch'] = etree.tostring(root)
913                     result['fields'] = {}
914                     result['context'] = context
915         return result
916
917     def create_report(self, cr, uid, res_ids, report_name=False, file_name=False, context=None):
918         if not report_name or not res_ids:
919             return (False, Exception('Report name and Resources ids are required !!!'))
920         try:
921             ret_file_name = '/tmp/'+file_name+'.pdf'
922             service = netsvc.LocalService(report_name);
923             (result, format) = service.create(cr, uid, res_ids, {}, context)
924             fp = open(ret_file_name, 'wb+');
925             fp.write(result);
926             fp.close();
927         except Exception,e:
928             print 'Exception in create report:',e
929             return (False, str(e))
930         return (True, ret_file_name)
931
932     def default_get(self, cr, uid, fields_list, context=None):
933         value = {}
934         for field in fields_list:
935             if field.split('_')[0] == 'progress':
936                 tot_page_id = self.pool.get('survey').browse(cr, uid, context['survey_id'])
937                 tot_per = (float(100) * (int(field.split('_')[2]) + 1) / len(tot_page_id.page_ids))
938                 value[field] = tot_per
939         if context.has_key('active') and context['active']:
940             return value
941         surv_name_wiz = self.pool.get('survey.name.wiz')
942         sur_name_read = surv_name_wiz.read(cr, uid, context['sur_name_id'])
943         ans_list = []
944         for key,val in sur_name_read['store_ans'].items():
945             for field in fields_list:
946                 if field in list(val):
947                     value[field] = val[field]
948         return value
949
950     def create(self, cr, uid, vals, context=None):
951         if context.has_key('active') and context['active']:
952             return True
953         for key,val in vals.items():
954             if key.split('_')[0] == "progress":
955                 vals.pop(key)
956                 break
957         click_state = True
958         click_update = []
959         surv_name_wiz = self.pool.get('survey.name.wiz')
960         surv_all_resp_obj = self.pool.get('survey.response')
961         surv_tbl_column_obj = self.pool.get('survey.tbl.column.heading')
962         sur_name_read = surv_name_wiz.read(cr, uid, context['sur_name_id'])
963         response_id =  0
964         if not sur_name_read['response']:
965             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']})
966             surv_name_wiz.write(cr, uid, [context['sur_name_id']], {'response' : tools.ustr(response_id)})
967         else:
968             response_id = int(sur_name_read['response'])
969         if response_id not in surv_all_resp_obj.search(cr, uid, []):
970             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']})
971             surv_name_wiz.write(cr, uid, [context['sur_name_id']], {'response' : tools.ustr(response_id)})
972         for key,val in sur_name_read['store_ans'].items():
973             for field in vals:
974                 if field.split('_')[0] == val['question_id']:
975                     click_state = False
976                     click_update.append(key)
977                     break
978         resp_obj = self.pool.get('survey.response.line')
979         res_ans_obj = self.pool.get('survey.response.answer')
980         que_obj = self.pool.get('survey.question')
981         if click_state:
982             que_li = []
983             resp_id_list = []
984             for key, val in vals.items():
985                 que_id = key.split('_')[0]
986                 if que_id not in que_li:
987                     que_li.append(que_id)
988                     que_rec = que_obj.read(cr, uid, [int(que_id)], [])[0]
989                     resp_id = resp_obj.create(cr, uid, {'question_id':que_id, 'date_create':datetime.datetime.now(), \
990                          'state':'done','response_id' : response_id })
991                     resp_id_list.append(resp_id)
992                     sur_name_read['store_ans'].update({resp_id:{'question_id':que_id}})
993                     surv_name_wiz.write(cr, uid, [context['sur_name_id']], {'store_ans':sur_name_read['store_ans']})
994                     select_count = 0
995                     numeric_sum = 0
996                     selected_value = []
997                     matrix_list = []
998                     comment_field = False
999                     comment_value = False
1000                     response_list = []
1001                     for key1, val1 in vals.items():
1002                         if val1 and key1.split('_')[1] == "table" and key1.split('_')[0] == que_id:
1003                             surv_tbl_column_obj.create(cr, uid, {'response_table_id' : resp_id,'column_id':key1.split('_')[2], 'name':key1.split('_')[3], 'value' : val1})
1004                             sur_name_read['store_ans'][resp_id].update({key1:val1})
1005                             select_count += 1
1006                         elif val1 and key1.split('_')[1] == "otherfield" and key1.split('_')[0] == que_id:
1007                             comment_field = True
1008                             sur_name_read['store_ans'][resp_id].update({key1:val1})
1009                             select_count += 1
1010                             surv_name_wiz.write(cr, uid, [context['sur_name_id']], {'store_ans':sur_name_read['store_ans']})
1011                             continue
1012                         elif val1 and key1.split('_')[1] == "selection" and key1.split('_')[0] == que_id:
1013                             if len(key1.split('_')) > 2:
1014                                 ans_create_id = res_ans_obj.create(cr, uid, {'response_id':resp_id, 'answer_id':key1.split('_')[-1], 'column_id' : val1})
1015                                 selected_value.append(val1)
1016                                 response_list.append(str(ans_create_id) + "_" + str(key1.split('_')[-1]))
1017                             else:
1018                                 ans_create_id = res_ans_obj.create(cr, uid, {'response_id':resp_id, 'answer_id':val1})
1019                             sur_name_read['store_ans'][resp_id].update({key1:val1})
1020                             select_count += 1
1021                         elif key1.split('_')[1] == "other" and key1.split('_')[0] == que_id:
1022                             if not val1:
1023                                 comment_value = True
1024                             else:
1025                                 error = False
1026                                 if que_rec['comment_valid_type'] == 'must_be_specific_length':
1027                                     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']:
1028                                         error = True
1029                                 elif que_rec['comment_valid_type'] in ['must_be_whole_number', 'must_be_decimal_number', 'must_be_date']:
1030                                     error = False
1031                                     try:
1032                                         if que_rec['comment_valid_type'] == 'must_be_whole_number':
1033                                             value = int(val1)
1034                                             if value <  que_rec['comment_minimum_no'] or value > que_rec['comment_maximum_no']:
1035                                                 error = True
1036                                         elif que_rec['comment_valid_type'] == 'must_be_decimal_number':
1037                                             value = float(val1)
1038                                             if value <  que_rec['comment_minimum_float'] or value > que_rec['comment_maximum_float']:
1039                                                 error = True
1040                                         elif que_rec['comment_valid_type'] == 'must_be_date':
1041                                             value = datetime.datetime.strptime(val1, "%Y-%m-%d")
1042                                             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"):
1043                                                 error = True
1044                                     except:
1045                                         error = True
1046                                 elif que_rec['comment_valid_type'] == 'must_be_email_address':
1047                                     import re
1048                                     if re.match("^[a-zA-Z0-9._%-+]+@[a-zA-Z0-9._%-]+.[a-zA-Z]{2,6}$", val1) == None:
1049                                             error = True
1050                                 if error:
1051                                     for res in resp_id_list:
1052                                         sur_name_read['store_ans'].pop(res)
1053                                     raise osv.except_osv(_('Error !'), _("'" + que_rec['question'] + "'  \n" + tools.ustr(que_rec['comment_valid_err_msg'])))
1054                                 resp_obj.write(cr, uid, resp_id, {'comment':val1})
1055                                 sur_name_read['store_ans'][resp_id].update({key1:val1})
1056                         elif val1 and key1.split('_')[1] == "comment" and key1.split('_')[0] == que_id:
1057                             resp_obj.write(cr, uid, resp_id, {'comment':val1})
1058                             sur_name_read['store_ans'][resp_id].update({key1:val1})
1059                             select_count += 1
1060                         elif val1 and key1.split('_')[0] == que_id and (key1.split('_')[1] == "single"  or (len(key1.split('_')) > 2 and key1.split('_')[2] == 'multi')):
1061                             error = False
1062                             if que_rec['validation_type'] == 'must_be_specific_length':
1063                                 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']:
1064                                     error = True
1065                             elif que_rec['validation_type'] in ['must_be_whole_number', 'must_be_decimal_number', 'must_be_date']:
1066                                 error = False
1067                                 try:
1068                                     if que_rec['validation_type'] == 'must_be_whole_number':
1069                                         value = int(val1)
1070                                         if value <  que_rec['validation_minimum_no'] or value > que_rec['validation_maximum_no']:
1071                                             error = True
1072                                     elif que_rec['validation_type'] == 'must_be_decimal_number':
1073                                         value = float(val1)
1074                                         if value <  que_rec['validation_minimum_float'] or value > que_rec['validation_maximum_float']:
1075                                             error = True
1076                                     elif que_rec['validation_type'] == 'must_be_date':
1077                                         value = datetime.datetime.strptime(val1, "%Y-%m-%d")
1078                                         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"):
1079                                             error = True
1080                                 except:
1081                                     error = True
1082                             elif que_rec['validation_type'] == 'must_be_email_address':
1083                                 import re
1084                                 if re.match("^[a-zA-Z0-9._%-+]+@[a-zA-Z0-9._%-]+.[a-zA-Z]{2,6}$", val1) == None:
1085                                         error = True
1086                             if error:
1087                                 for res in resp_id_list:
1088                                     sur_name_read['store_ans'].pop(res)
1089                                 raise osv.except_osv(_('Error !'), _("'" + que_rec['question'] + "'  \n" + tools.ustr(que_rec['validation_valid_err_msg'])))
1090                             if key1.split('_')[1] == "single" :
1091                                 resp_obj.write(cr, uid, resp_id, {'single_text':val1})
1092                             else:
1093                                 ans_create_id = res_ans_obj.create(cr, uid, {'response_id':resp_id, 'answer_id':key1.split('_')[1], 'answer' : val1})
1094                             sur_name_read['store_ans'][resp_id].update({key1:val1})
1095                             select_count += 1
1096                         elif val1 and que_id == key1.split('_')[0] and len(key1.split('_')) > 2 and key1.split('_')[2] == 'numeric':
1097                             ans_create_id = res_ans_obj.create(cr, uid, {'response_id':resp_id, 'answer_id':key1.split('_')[1], 'answer' : val1})
1098                             sur_name_read['store_ans'][resp_id].update({key1:val1})
1099                             select_count += 1
1100                             numeric_sum += int(val1)
1101                         elif val1 and que_id == key1.split('_')[0] and len(key1.split('_')) == 3:
1102                             if type(val1) == type('') or type(val1) == type(u''):
1103                                 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})
1104                                 sur_name_read['store_ans'][resp_id].update({key1:val1})
1105                             else:
1106                                 ans_create_id = res_ans_obj.create(cr, uid, {'response_id':resp_id, 'answer_id':key1.split('_')[1], 'column_id' : key1.split('_')[2]})
1107                                 sur_name_read['store_ans'][resp_id].update({key1:True})
1108                             matrix_list.append(key1.split('_')[0] + '_' + key1.split('_')[1])
1109                             select_count += 1
1110                         elif val1 and que_id == key1.split('_')[0] and len(key1.split('_')) == 2:
1111                             ans_create_id = res_ans_obj.create(cr, uid, {'response_id':resp_id, 'answer_id':key1.split('_')[-1], 'answer' : val1})
1112                             sur_name_read['store_ans'][resp_id].update({key1:val1})
1113                             select_count += 1
1114                         surv_name_wiz.write(cr, uid, [context['sur_name_id']], {'store_ans':sur_name_read['store_ans']})
1115                     for key,val in vals.items():
1116                         if val and key.split('_')[1] == "commentcolumn" and key.split('_')[0] == que_id:
1117                             for res_id in response_list:
1118                                 if key.split('_')[2] in res_id.split('_')[1]:
1119                                     a = res_ans_obj.write(cr, uid, [res_id.split('_')[0]], {'comment_field':val})
1120                                     sur_name_read['store_ans'][resp_id].update({key:val})
1121                     if comment_field and comment_value:
1122                         for res in resp_id_list:
1123                             sur_name_read['store_ans'].pop(res)
1124                         raise osv.except_osv(_('Error re !'), _("'" + que_rec['question']  + "' " + tools.ustr(que_rec['make_comment_field_err_msg'])))
1125                     if que_rec['type'] == "rating_scale" and que_rec['rating_allow_one_column_require'] and len(selected_value) > len(list(set(selected_value))):
1126                         for res in resp_id_list:
1127                             sur_name_read['store_ans'].pop(res)
1128                         raise osv.except_osv(_('Error re !'), _("'" + que_rec['question'] + "\n you cannot select same answer more than one times'"))
1129                     if not select_count:
1130                         resp_obj.write(cr, uid, resp_id, {'state':'skip'})
1131                     if que_rec['numeric_required_sum'] and numeric_sum > que_rec['numeric_required_sum']:
1132                         for res in resp_id_list:
1133                             sur_name_read['store_ans'].pop(res)
1134                         raise osv.except_osv(_('Error re !'), _("'" + que_rec['question'] + "' " + tools.ustr(que_rec['numeric_required_sum_err_msg'])))
1135                     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']:
1136                         if matrix_list:
1137                             if (que_rec['required_type'] == 'all' and len(list(set(matrix_list))) < len(que_rec['answer_choice_ids'])) or \
1138                             (que_rec['required_type'] == 'at least' and len(list(set(matrix_list))) < que_rec['req_ans']) or \
1139                             (que_rec['required_type'] == 'at most' and len(list(set(matrix_list))) > que_rec['req_ans']) or \
1140                             (que_rec['required_type'] == 'exactly' and len(list(set(matrix_list))) != que_rec['req_ans']) or \
1141                             (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'])):
1142                                 for res in resp_id_list:
1143                                     sur_name_read['store_ans'].pop(res)
1144                                 raise osv.except_osv(_('Error !'), _("'" + que_rec['question'] + "' " + tools.ustr(que_rec['req_error_msg'])))
1145                         elif (que_rec['required_type'] == 'all' and select_count < len(que_rec['answer_choice_ids'])) or \
1146                             (que_rec['required_type'] == 'at least' and select_count < que_rec['req_ans']) or \
1147                             (que_rec['required_type'] == 'at most' and select_count > que_rec['req_ans']) or \
1148                             (que_rec['required_type'] == 'exactly' and select_count != que_rec['req_ans']) or \
1149                             (que_rec['required_type'] == 'a range' and (select_count < que_rec['minimum_req_ans'] or select_count > que_rec['maximum_req_ans'])):
1150                             for res in resp_id_list:
1151                                 sur_name_read['store_ans'].pop(res)
1152                             raise osv.except_osv(_('Error !'), _("'" + que_rec['question'] + "' " + tools.ustr(que_rec['req_error_msg'])))
1153                     if que_rec['type'] in ['multiple_choice_only_one_ans','single_textbox','comment'] and  que_rec['is_require_answer'] and select_count <= 0:
1154                         for res in resp_id_list:
1155                             sur_name_read['store_ans'].pop(res)
1156                         raise osv.except_osv(_('Error re !'), _("'" + que_rec['question'] + "' " + tools.ustr(que_rec['req_error_msg'])))
1157         else:
1158             resp_id_list = []
1159             for update in click_update:
1160                 que_rec = que_obj.read(cr, uid , [int(sur_name_read['store_ans'][update]['question_id'])], [])[0]
1161                 res_ans_obj.unlink(cr, uid,res_ans_obj.search(cr, uid, [('response_id', '=', update)]))
1162                 surv_tbl_column_obj.unlink(cr, uid,surv_tbl_column_obj.search(cr, uid, [('response_table_id', '=', update)]))
1163                 resp_id_list.append(update)
1164                 sur_name_read['store_ans'].update({update:{'question_id':sur_name_read['store_ans'][update]['question_id']}})
1165                 surv_name_wiz.write(cr, uid, [context['sur_name_id']], {'store_ans':sur_name_read['store_ans']})
1166                 select_count = 0
1167                 numeric_sum = 0
1168                 selected_value = []
1169                 matrix_list = []
1170                 comment_field = False
1171                 comment_value = False
1172                 response_list = []
1173                 for key, val in vals.items():
1174                     ans_id_len = key.split('_')
1175                     if ans_id_len[0] == sur_name_read['store_ans'][update]['question_id']:
1176                         if val and key.split('_')[1] == "table":
1177                             surv_tbl_column_obj.create(cr, uid, {'response_table_id' : update,'column_id':key.split('_')[2], 'name':key.split('_')[3], 'value' : val})
1178                             sur_name_read['store_ans'][update].update({key:val})
1179                             resp_obj.write(cr, uid, update, {'state': 'done'})
1180                         elif val and key.split('_')[1] == "otherfield" :
1181                             comment_field = True
1182                             sur_name_read['store_ans'][update].update({key:val})
1183                             select_count += 1
1184                             surv_name_wiz.write(cr, uid, [context['sur_name_id']], {'store_ans':sur_name_read['store_ans']})
1185                             continue
1186                         elif val and key.split('_')[1] == "selection":
1187                             if len(key.split('_')) > 2:
1188                                 ans_create_id = res_ans_obj.create(cr, uid, {'response_id':update, 'answer_id':key.split('_')[-1], 'column_id' : val})
1189                                 selected_value.append(val)
1190                                 response_list.append(str(ans_create_id) + "_" + str(key.split('_')[-1]))
1191                             else:
1192                                 ans_create_id = res_ans_obj.create(cr, uid, {'response_id':update, 'answer_id': val})
1193                             resp_obj.write(cr, uid, update, {'state': 'done'})
1194                             sur_name_read['store_ans'][update].update({key:val})
1195                             select_count += 1
1196                         elif key.split('_')[1] == "other":
1197                             if not val:
1198                                 comment_value = True
1199                             else:
1200                                 error = False
1201                                 if que_rec['comment_valid_type'] == 'must_be_specific_length':
1202                                     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']:
1203                                         error = True
1204                                 elif que_rec['comment_valid_type'] in ['must_be_whole_number', 'must_be_decimal_number', 'must_be_date']:
1205                                     try:
1206                                         if que_rec['comment_valid_type'] == 'must_be_whole_number':
1207                                             value = int(val)
1208                                             if value <  que_rec['comment_minimum_no'] or value > que_rec['comment_maximum_no']:
1209                                                 error = True
1210                                         elif que_rec['comment_valid_type'] == 'must_be_decimal_number':
1211                                             value = float(val)
1212                                             if value <  que_rec['comment_minimum_float'] or value > que_rec['comment_maximum_float']:
1213                                                 error = True
1214                                         elif que_rec['comment_valid_type'] == 'must_be_date':
1215                                             value = datetime.datetime.strptime(val, "%Y-%m-%d")
1216                                             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"):
1217                                                 error = True
1218                                     except:
1219                                         error = True
1220                                 elif que_rec['comment_valid_type'] == 'must_be_email_address':
1221                                     import re
1222                                     if re.match("^[a-zA-Z0-9._%-+]+@[a-zA-Z0-9._%-]+.[a-zA-Z]{2,6}$", val) == None:
1223                                             error = True
1224                                 if error:
1225                                     raise osv.except_osv(_('Error !'), _("'" + que_rec['question'] + "'  \n" + tools.ustr(que_rec['comment_valid_err_msg'])))
1226                                 resp_obj.write(cr, uid, update, {'comment':val,'state': 'done'})
1227                                 sur_name_read['store_ans'][update].update({key:val})
1228                         elif val and key.split('_')[1] == "comment":
1229                             resp_obj.write(cr, uid, update, {'comment':val,'state': 'done'})
1230                             sur_name_read['store_ans'][update].update({key:val})
1231                             select_count += 1
1232                         elif val and (key.split('_')[1] == "single"  or (len(key.split('_')) > 2 and key.split('_')[2] == 'multi')):
1233                             error = False
1234                             if que_rec['validation_type'] == 'must_be_specific_length':
1235                                 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']:
1236                                     error = True
1237                             elif que_rec['validation_type'] in ['must_be_whole_number', 'must_be_decimal_number', 'must_be_date']:
1238                                 error = False
1239                                 try:
1240                                     if que_rec['validation_type'] == 'must_be_whole_number':
1241                                         value = int(val)
1242                                         if value <  que_rec['validation_minimum_no'] or value > que_rec['validation_maximum_no']:
1243                                             error = True
1244                                     elif que_rec['validation_type'] == 'must_be_decimal_number':
1245                                         value = float(val)
1246                                         if value <  que_rec['validation_minimum_float'] or value > que_rec['validation_maximum_float']:
1247                                             error = True
1248                                     elif que_rec['validation_type'] == 'must_be_date':
1249                                         value = datetime.datetime.strptime(val, "%Y-%m-%d")
1250                                         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"):
1251                                             error = True
1252                                 except Exception ,e:
1253                                     error = True
1254                             elif que_rec['validation_type'] == 'must_be_email_address':
1255                                 import re
1256                                 if re.match("^[a-zA-Z0-9._%-+]+@[a-zA-Z0-9._%-]+.[a-zA-Z]{2,6}$", val) == None:
1257                                         error = True
1258                             if error:
1259                                 raise osv.except_osv(_('Error !'), _("'" + que_rec['question'] + "'  \n" + tools.ustr(que_rec['validation_valid_err_msg'])))
1260                             if key.split('_')[1] == "single" :
1261                                 resp_obj.write(cr, uid, update, {'single_text':val,'state': 'done'})
1262                             else:
1263                                 resp_obj.write(cr, uid, update, {'state': 'done'})
1264                                 ans_create_id = res_ans_obj.create(cr, uid, {'response_id':update, 'answer_id':ans_id_len[1], 'answer' : val})
1265                             sur_name_read['store_ans'][update].update({key:val})
1266                             select_count += 1
1267                         elif val and len(key.split('_')) > 2 and key.split('_')[2] == 'numeric':
1268                             resp_obj.write(cr, uid, update, {'state': 'done'})
1269                             ans_create_id = res_ans_obj.create(cr, uid, {'response_id':update, 'answer_id':ans_id_len[1], 'answer' : val})
1270                             sur_name_read['store_ans'][update].update({key:val})
1271                             select_count += 1
1272                             numeric_sum += int(val)
1273                         elif val and len(key.split('_')) == 3:
1274                             resp_obj.write(cr, uid, update, {'state': 'done'})
1275                             if type(val) == type('') or type(val) == type(u''):
1276                                 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})
1277                                 sur_name_read['store_ans'][update].update({key:val})
1278                             else:
1279                                 ans_create_id = res_ans_obj.create(cr, uid, {'response_id':update, 'answer_id':ans_id_len[1], 'column_id' : ans_id_len[2]})
1280                                 sur_name_read['store_ans'][update].update({key:True})
1281                             matrix_list.append(key.split('_')[0] + '_' + key.split('_')[1])
1282                             select_count += 1
1283                         elif val and len(key.split('_')) == 2:
1284                             resp_obj.write(cr, uid, update, {'state': 'done'})
1285                             ans_create_id = res_ans_obj.create(cr, uid, {'response_id':update, 'answer_id':ans_id_len[-1], 'answer' : val})
1286                             sur_name_read['store_ans'][update].update({key:val})
1287                             select_count += 1
1288                         surv_name_wiz.write(cr, uid, [context['sur_name_id']], {'store_ans':sur_name_read['store_ans']})
1289                 for key,val in vals.items():
1290                     if val and key.split('_')[1] == "commentcolumn" and key.split('_')[0] == sur_name_read['store_ans'][update]['question_id']:
1291                         for res_id in response_list:
1292                             if key.split('_')[2] in res_id.split('_')[1]:
1293                                 a = res_ans_obj.write(cr, uid, [res_id.split('_')[0]], {'comment_field':val})
1294                                 sur_name_read['store_ans'][update].update({key:val})
1295                 if comment_field and comment_value:
1296                     raise osv.except_osv(_('Error re !'), _("'" + que_rec['question']  + "' " + tools.ustr(que_rec['make_comment_field_err_msg'])))
1297                 if que_rec['type'] == "rating_scale" and que_rec['rating_allow_one_column_require'] and len(selected_value) > len(list(set(selected_value))):
1298                     raise osv.except_osv(_('Error re !'), _("'" + que_rec['question'] + "\n you cannot select same answer more than one times'"))
1299                 if que_rec['numeric_required_sum'] and numeric_sum > que_rec['numeric_required_sum']:
1300                     raise osv.except_osv(_('Error re !'), _("'" + que_rec['question'] + "' " + tools.ustr(que_rec['numeric_required_sum_err_msg'])))
1301                 if not select_count:
1302                     resp_obj.write(cr, uid, update, {'state': 'skip'})
1303                 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']:
1304                     if matrix_list:
1305                         if (que_rec['required_type'] == 'all' and len(list(set(matrix_list))) < len(que_rec['answer_choice_ids'])) or \
1306                         (que_rec['required_type'] == 'at least' and len(list(set(matrix_list))) < que_rec['req_ans']) or \
1307                         (que_rec['required_type'] == 'at most' and len(list(set(matrix_list))) > que_rec['req_ans']) or \
1308                         (que_rec['required_type'] == 'exactly' and len(list(set(matrix_list))) != que_rec['req_ans']) or \
1309                         (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'])):
1310                             raise osv.except_osv(_('Error !'), _("'" + que_rec['question'] + "' " + tools.ustr(que_rec['req_error_msg'])))
1311                     elif (que_rec['required_type'] == 'all' and select_count < len(que_rec['answer_choice_ids'])) or \
1312                         (que_rec['required_type'] == 'at least' and select_count < que_rec['req_ans']) or \
1313                         (que_rec['required_type'] == 'at most' and select_count > que_rec['req_ans']) or \
1314                         (que_rec['required_type'] == 'exactly' and select_count != que_rec['req_ans']) or \
1315                         (que_rec['required_type'] == 'a range' and (select_count < que_rec['minimum_req_ans'] or select_count > que_rec['maximum_req_ans'])):
1316                             raise osv.except_osv(_('Error !'), _("'" + que_rec['question'] + "' " + tools.ustr(que_rec['req_error_msg'])))
1317                 if que_rec['type'] in ['multiple_choice_only_one_ans','single_textbox','comment'] and  que_rec['is_require_answer'] and select_count <= 0:
1318                     raise osv.except_osv(_('Error re !'), _("'" + que_rec['question'] + "' " + tools.ustr(que_rec['req_error_msg'])))
1319         return True
1320
1321     def action_new_question(self,cr, uid, ids, context):
1322         for key,val in context.items():
1323             if type(key) == type(True):
1324                 context.pop(key)
1325         view_id = self.pool.get('ir.ui.view').search(cr,uid,[('model','=','survey.question'),('name','=','survey_question_wizard_test')])
1326         return {
1327                 'view_type': 'form',
1328                 "view_mode": 'form',
1329                 'res_model': 'survey.question',
1330                 'type': 'ir.actions.act_window',
1331                 'target': 'new',
1332                 'view_id': view_id,
1333                 'context': context
1334                 }
1335
1336     def action_new_page(self, cr, uid, ids, context):
1337         for key,val in context.items():
1338             if type(key) == type(True):
1339                 context.pop(key)
1340         view_id = self.pool.get('ir.ui.view').search(cr,uid,[('model','=','survey.page'),('name','=','survey_page_wizard_test')])
1341         return {
1342                 'view_type': 'form',
1343                 "view_mode": 'form',
1344                 'res_model': 'survey.page',
1345                 'type': 'ir.actions.act_window',
1346                 'target': 'new',
1347                 'view_id': view_id,
1348                 'context': context
1349                 }
1350
1351     def action_edit_page(self,cr, uid, ids, context):
1352         for key,val in context.items():
1353             if type(key) == type(True):
1354                 context.pop(key)
1355         view_id = self.pool.get('ir.ui.view').search(cr,uid,[('model','=','survey.page'),('name','=','survey_page_wizard_test')])
1356         return {
1357                 'view_type': 'form',
1358                 "view_mode": 'form',
1359                 'res_model': 'survey.page',
1360                 'type': 'ir.actions.act_window',
1361                 'target': 'new',
1362                 'res_id' : int(context['page_id']),
1363                 'view_id': view_id,
1364                 'context': context
1365                 }
1366
1367     def action_delete_page(self,cr, uid, ids, context):
1368         for key,val in context.items():
1369             if type(key) == type(True):
1370                 context.pop(key)
1371         self.pool.get('survey.page').unlink(cr, uid, [context['page_id']])
1372         search_id = self.pool.get('ir.ui.view').search(cr,uid,[('model','=','survey.question.wiz'),('name','=','Survey Search')])
1373         surv_name_wiz = self.pool.get('survey.name.wiz')
1374         surv_name_wiz.write(cr, uid, [context['sur_name_id']], {'transfer':True, 'page_no' : context['page_number'] })
1375         return {
1376                 'view_type': 'form',
1377                 "view_mode": 'form',
1378                 'res_model': 'survey.question.wiz',
1379                 'type': 'ir.actions.act_window',
1380                 'target': 'new',
1381                 'search_view_id':search_id[0],
1382                 'context': context
1383                 }
1384
1385     def action_edit_question(self,cr, uid, ids, context):
1386         for key,val in context.items():
1387             if type(key) == type(True):
1388                 context.pop(key)
1389         view_id = self.pool.get('ir.ui.view').search(cr,uid,[('model','=','survey.question'),('name','=','survey_question_wizard_test')])
1390         return {
1391                 'view_type': 'form',
1392                 "view_mode": 'form',
1393                 'res_model': 'survey.question',
1394                 'type': 'ir.actions.act_window',
1395                 'target': 'new',
1396                 'res_id' : int(context['question_id']),
1397                 'view_id': view_id,
1398                 'context': context
1399                 }
1400
1401     def action_delete_question(self,cr, uid, ids, context):
1402         for key,val in context.items():
1403             if type(key) == type(True):
1404                 context.pop(key)
1405         que_obj = self.pool.get('survey.question')
1406         que_obj.unlink(cr, uid, [context['question_id']])
1407         search_id = self.pool.get('ir.ui.view').search(cr,uid,[('model','=','survey.question.wiz'),('name','=','Survey Search')])
1408         surv_name_wiz = self.pool.get('survey.name.wiz')
1409         surv_name_wiz.write(cr, uid, [context['sur_name_id']], {'transfer':True, 'page_no' : context['page_number'] })
1410         return {
1411                 'view_type': 'form',
1412                 "view_mode": 'form',
1413                 'res_model': 'survey.question.wiz',
1414                 'type': 'ir.actions.act_window',
1415                 'target': 'new',
1416                 'search_view_id':search_id[0],
1417                 'context': context
1418                 }
1419
1420     def action_next(self, cr, uid, ids, context=None):
1421         surv_name_wiz = self.pool.get('survey.name.wiz')
1422         search_obj = self.pool.get('ir.ui.view')
1423         search_id = search_obj.search(cr,uid,[('model','=','survey.question.wiz'),('name','=','Survey Search')])
1424         surv_name_wiz.write(cr, uid, [context['sur_name_id']], {'transfer':True, 'page':'next'})
1425         return {
1426                 'view_type': 'form',
1427                 "view_mode": 'form',
1428                 'res_model': 'survey.question.wiz',
1429                 'type': 'ir.actions.act_window',
1430                 'target': 'new',
1431                 'search_view_id':search_id[0],
1432                 'context': context
1433                 }
1434
1435     def action_previous(self, cr, uid, ids, context=None):
1436         surv_name_wiz = self.pool.get('survey.name.wiz')
1437         search_obj = self.pool.get('ir.ui.view')
1438         search_id = search_obj.search(cr,uid,[('model','=','survey.question.wiz'),('name','=','Survey Search')])
1439         surv_name_wiz.write(cr, uid, [context['sur_name_id']], {'transfer':True, 'page':'previous'})
1440         return {
1441                 'view_type': 'form',
1442                 "view_mode": 'form',
1443                 'res_model': 'survey.question.wiz',
1444                 'type': 'ir.actions.act_window',
1445                 'target': 'new',
1446                 'search_view_id':search_id[0],
1447                 'context': context
1448                 }
1449
1450 survey_question_wiz()
1451
1452 class res_users(osv.osv):
1453     _inherit = "res.users"
1454     _name = "res.users"
1455     _columns = {
1456         'survey_id': fields.many2many('survey', 'survey_users_rel', 'uid', 'sid', 'Groups'),
1457     }
1458
1459 res_users()
1460
1461 class survey_request(osv.osv):
1462     _name = "survey.request"
1463     _order = 'date_deadline'
1464     _rec_name = 'date_deadline'
1465     _columns = {
1466         'date_deadline' : fields.date("Deadline date"),
1467         'user_id' : fields.many2one("res.users", "User"),
1468         'email' : fields.char("E-mail", size=64),
1469         'survey_id' : fields.many2one("survey", "Survey", required=1),
1470         'answer_ids' : fields.one2many('survey.answer', 'question_id', 'Answer'),
1471         'state' : fields.selection([('waiting_answer', 'Wating Answer'),('done', 'Done'),('cancel', 'Cancelled')], 'State', readonly=1)
1472     }
1473     _defaults = {
1474         'state' : lambda * a: 'waiting_answer',
1475         'date_deadline' : lambda * a :  (now() + RelativeDateTime(months=+1)).strftime("%Y-%m-%d %H:%M:%S")
1476     }
1477     def survey_req_waiting_answer(self, cr, uid, ids, arg):
1478         self.write(cr, uid, ids, { 'state' : 'waiting_answer'})
1479         return True
1480
1481     def survey_req_done(self, cr, uid, ids, arg):
1482         self.write(cr, uid, ids, { 'state' : 'done'})
1483         return True
1484
1485     def survey_req_cancel(self, cr, uid, ids, arg):
1486         self.write(cr, uid, ids, { 'state' : 'cancel'})
1487         return True
1488
1489     def on_change_user(self, cr, uid, ids, user_id, context=None):
1490         if user_id:
1491             user_obj = self.pool.get('res.users')
1492             user = user_obj.browse(cr, uid, user_id)
1493             return {'value': {'email': user.address_id.email}}
1494         return {}
1495
1496 survey_request()
1497
1498 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: