2010-01-20 14:28:28 +00:00
# -*- encoding: utf-8 -*-
##############################################################################
#
# OpenERP, Open Source Management Solution
2013-10-21 09:03:19 +00:00
# Copyright (C) 2004-TODAY OpenERP S.A. <http: //www.openerp.com>
2010-01-20 14:28:28 +00:00
#
2013-10-21 09:03:19 +00:00
# This program is free software: you can redistribute it and / or modify
2010-12-08 13:59:16 +00:00
# it under the terms of the GNU Affero General Public License as
# published by the Free Software Foundation, either version 3 of the
# License, or (at your option) any later version.
2010-01-20 14:28:28 +00:00
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2010-12-08 13:59:16 +00:00
# GNU Affero General Public License for more details.
2010-01-20 14:28:28 +00:00
#
2010-12-08 13:59:16 +00:00
# You should have received a copy of the GNU Affero General Public License
2013-10-21 09:03:19 +00:00
# along with this program. If not, see <http: //www.gnu.org/licenses/>.
2010-01-20 14:28:28 +00:00
#
##############################################################################
2013-10-21 09:03:19 +00:00
from urllib import urlencode
from urlparse import urljoin
2012-12-06 14:56:32 +00:00
from openerp . osv import fields , osv
from openerp . tools . translate import _
2013-10-21 09:03:19 +00:00
import uuid
2010-01-27 13:55:23 +00:00
2013-10-28 07:51:21 +00:00
class survey_survey ( osv . osv ) :
2013-10-22 15:10:51 +00:00
''' Settings for a multi-page/multi-question survey.
Each survey can have one or more attached pages , and each page can present
one or more questions .
'''
_name = ' survey.survey '
2010-01-20 14:28:28 +00:00
_description = ' Survey '
_rec_name = ' title '
2013-10-21 09:03:19 +00:00
_inherit = [ ' mail.thread ' , ' ir.needaction_mixin ' ]
2010-01-27 13:55:23 +00:00
2013-10-22 15:10:51 +00:00
# Protected methods #
2013-10-25 09:56:54 +00:00
def _empty_check ( self , cr , uid , ids , context = None ) :
""" Ensure that this survey has at least one page with at least one
question . If not , raises an exception . """
2013-10-28 16:15:31 +00:00
for survey in self . browse ( cr , uid , ids , context = context ) :
2013-10-25 09:56:54 +00:00
if not survey . page_ids or not [ page . question_ids
for page in survey . page_ids if page . question_ids ] :
raise osv . except_osv ( _ ( ' Warning! ' ) ,
_ ( ' This survey has no question defined or has no pages \
defined . ' ))
2013-10-24 09:26:33 +00:00
## Function fields ##
2013-10-21 09:03:19 +00:00
def _get_tot_start_survey ( self , cr , uid , ids , name , arg , context = None ) :
2013-10-23 09:03:42 +00:00
""" Returns the number of started instances of this survey, be they
completed or not """
2013-10-21 09:03:19 +00:00
res = dict ( ( id , 0 ) for id in ids )
2013-10-28 07:51:21 +00:00
sur_res_obj = self . pool . get ( ' survey.user_input ' )
2013-10-21 09:03:19 +00:00
for id in ids :
2013-10-28 16:15:31 +00:00
res [ id ] = sur_res_obj . search ( cr , uid , # SUPERUSER_ID,
2013-10-28 07:51:21 +00:00
[ ( ' survey_id ' , ' = ' , id ) , ( ' state ' , ' = ' , ' skip ' ) ] ,
context = context , count = True )
2013-10-21 09:03:19 +00:00
return res
def _get_tot_comp_survey ( self , cr , uid , ids , name , arg , context = None ) :
2013-10-23 09:03:42 +00:00
""" Returns the number of completed instances of this survey """
2013-10-21 09:03:19 +00:00
res = dict ( ( id , 0 ) for id in ids )
2013-10-28 07:51:21 +00:00
sur_res_obj = self . pool . get ( ' survey.user_input ' )
2013-10-21 09:03:19 +00:00
for id in ids :
2013-10-28 16:15:31 +00:00
res [ id ] = sur_res_obj . search ( cr , uid , # SUPERUSER_ID,
2013-10-28 07:51:21 +00:00
[ ( ' survey_id ' , ' = ' , id ) , ( ' state ' , ' = ' , ' done ' ) ] ,
context = context , count = True )
2013-10-21 09:03:19 +00:00
return res
def _get_public_url ( self , cr , uid , ids , name , arg , context = None ) :
2013-10-23 09:03:42 +00:00
""" Computes a public URL for the survey """
2013-10-21 09:03:19 +00:00
res = dict ( ( id , 0 ) for id in ids )
2013-10-23 09:03:42 +00:00
base_url = self . pool . get ( ' ir.config_parameter ' ) . get_param ( cr , uid ,
' web.base.url ' )
for survey_browse in self . browse ( cr , uid , ids , context = context ) :
2013-10-21 09:03:19 +00:00
query = {
' db ' : cr . dbname
}
fragment = {
2013-10-28 16:15:31 +00:00
#'survey_id': survey_browse.id,
2013-10-21 09:03:19 +00:00
' action ' : ' survey.action_filling ' ,
2013-10-28 16:15:31 +00:00
' survey_token ' : survey_browse . token ,
2013-10-21 09:03:19 +00:00
}
2013-10-28 07:51:21 +00:00
res [ survey_browse . id ] = urljoin ( base_url , " ? %s # %s "
% ( urlencode ( query ) , urlencode ( fragment ) ) )
2013-10-21 09:03:19 +00:00
return res
2010-01-27 13:55:23 +00:00
2013-10-22 15:10:51 +00:00
# Model fields #
2010-01-20 14:28:28 +00:00
_columns = {
2013-10-23 09:03:42 +00:00
' title ' : fields . char ( ' Title ' , size = 128 , required = 1 ,
translate = True ) ,
2013-10-23 12:22:55 +00:00
' category ' : fields . char ( ' Category ' , size = 128 ) ,
2013-10-22 15:10:51 +00:00
' page_ids ' : fields . one2many ( ' survey.page ' , ' survey_id ' , ' Pages ' ) ,
2013-10-28 14:43:14 +00:00
' date_open ' : fields . datetime ( ' Opening date ' ) ,
' date_close ' : fields . datetime ( ' Closing date ' ) ,
2013-10-23 09:03:42 +00:00
' user_input_limit ' : fields . integer ( ' Automatic closing limit ' ,
help = " Limits the number of instances of this survey that can be \
completed ( if set to 0 , no limit is applied " ,
oldname = ' max_response_limit ' ) ,
2013-10-22 15:10:51 +00:00
' state ' : fields . selection (
[ ( ' draft ' , ' Draft ' ) , ( ' open ' , ' Open ' ) , ( ' close ' , ' Closed ' ) ,
( ' cancel ' , ' Cancelled ' ) ] , ' Status ' , required = 1 , readonly = 1 ,
translate = 1 ) ,
2013-10-23 09:03:42 +00:00
' visible_to_user ' : fields . boolean ( ' Visible in the Surveys menu ' ) ,
' auth_required ' : fields . boolean ( ' Login required ' ,
help = " Users with a public link will be requested to login before \
takin part to the survey " , oldname= " authenticate " ),
' tot_start_survey ' : fields . function ( _get_tot_start_survey ,
string = " Number of started surveys " , type = " integer " ) ,
' tot_comp_survey ' : fields . function ( _get_tot_comp_survey ,
string = " Number of completed surveys " , type = " integer " ) ,
' description ' : fields . text ( ' Description ' , size = 128 , translate = True ,
oldname = " description " ) ,
2012-07-05 12:43:05 +00:00
' color ' : fields . integer ( ' Color Index ' ) ,
2013-10-23 09:03:42 +00:00
' user_input_ids ' : fields . one2many ( ' survey.user_input ' , ' survey_id ' ,
' User responses ' , readonly = 1 , ) ,
' public_url ' : fields . function ( _get_public_url ,
2013-10-28 16:15:31 +00:00
string = " Public link " , type = " char " , store = True ) ,
' token ' : fields . char ( ' Public token ' , size = 36 , required = True ,
readonly = True , ) ,
2013-10-23 09:03:42 +00:00
' email_template_id ' : fields . many2one ( ' email.template ' ,
' Email Template ' , ondelete = ' set null ' ) ,
2010-01-20 14:28:28 +00:00
}
_defaults = {
2013-10-23 09:03:42 +00:00
' category ' : ' Uncategorized ' ,
' user_input_limit ' : 0 ,
2013-10-22 15:10:51 +00:00
' state ' : ' draft ' ,
2013-10-21 09:03:19 +00:00
' visible_to_user ' : True ,
2013-10-23 09:03:42 +00:00
' auth_required ' : True ,
2013-10-28 14:43:14 +00:00
' token ' : lambda s , cr , uid , c : uuid . uuid4 ( ) . __str__ ( ) ,
2010-01-20 14:28:28 +00:00
}
2013-10-22 15:10:51 +00:00
# Public methods #
2013-10-25 09:56:54 +00:00
## Workflow transitions ##
2013-10-21 09:03:19 +00:00
def survey_draft ( self , cr , uid , ids , arg ) :
return self . write ( cr , uid , ids , { ' state ' : ' draft ' , ' date_open ' : None } )
2010-01-20 14:28:28 +00:00
def survey_open ( self , cr , uid , ids , arg ) :
2013-10-23 09:03:42 +00:00
return self . write ( cr , uid , ids , { ' state ' : ' open ' ,
2013-10-28 14:43:14 +00:00
' date_open ' : fields . datetime . now } )
2010-01-20 14:28:28 +00:00
def survey_close ( self , cr , uid , ids , arg ) :
2013-10-23 09:03:42 +00:00
return self . write ( cr , uid , ids , { ' state ' : ' close ' ,
2013-10-28 14:43:14 +00:00
' date_close ' : fields . datetime . now } )
2010-01-20 14:28:28 +00:00
def survey_cancel ( self , cr , uid , ids , arg ) :
2013-10-23 09:03:42 +00:00
return self . write ( cr , uid , ids , { ' state ' : ' cancel ' ,
2013-10-28 14:43:14 +00:00
' date_close ' : fields . datetime . now } )
2011-08-03 06:32:01 +00:00
2013-10-25 09:56:54 +00:00
## Actions ##
2010-12-14 07:37:12 +00:00
def copy ( self , cr , uid , ids , default = None , context = None ) :
2010-12-09 05:36:29 +00:00
vals = { }
current_rec = self . read ( cr , uid , ids , context = context )
2012-09-24 16:26:45 +00:00
title = _ ( " %s (copy) " ) % ( current_rec . get ( ' title ' ) )
2013-10-25 09:56:54 +00:00
vals [ ' title ' ] = title
2013-10-28 16:15:31 +00:00
return super ( survey_survey , self ) . copy ( cr , uid , ids , vals ,
context = context )
2010-02-05 11:25:40 +00:00
2013-10-25 09:56:54 +00:00
def action_print_survey_questions ( self , cr , uid , ids , context = None ) :
''' Generates a printable view of an empty survey '''
pass
2013-10-21 09:03:19 +00:00
2013-10-25 09:56:54 +00:00
def action_print_survey_user_inputs ( self , cr , uid , ids , context = None ) :
''' Generates printable views of answered surveys '''
pass
2012-09-24 16:26:45 +00:00
2013-10-25 09:56:54 +00:00
def action_print_survey_statistics ( self , cr , uid , ids , context = None ) :
''' Generates a printable view of the survey results '''
pass
2013-10-21 09:03:19 +00:00
def action_fill_survey ( self , cr , uid , ids , context = None ) :
2013-10-25 09:56:54 +00:00
''' Open a survey in filling view '''
2013-10-21 09:03:19 +00:00
id = ids [ 0 ]
survey = self . browse ( cr , uid , id , context = context )
2013-10-28 14:43:14 +00:00
context . update ( { ' edit ' : False , ' survey_id ' : id ,
' survey_token ' : survey . token ,
' ir_actions_act_window_target ' : ' inline ' } )
2012-04-17 05:50:10 +00:00
return {
' view_type ' : ' form ' ,
' view_mode ' : ' form ' ,
' res_model ' : ' survey.question.wiz ' ,
' type ' : ' ir.actions.act_window ' ,
2013-10-21 09:03:19 +00:00
' target ' : ' inline ' ,
' name ' : survey . title ,
2012-08-21 05:36:25 +00:00
' context ' : context
}
2013-10-21 09:03:19 +00:00
def action_test_survey ( self , cr , uid , ids , context = None ) :
2013-10-25 09:56:54 +00:00
''' Open a survey in filling view '''
2013-10-21 09:03:19 +00:00
context . update ( { ' survey_test ' : True } )
return self . action_fill_survey ( cr , uid , ids , context = context )
def action_edit_survey ( self , cr , uid , ids , context = None ) :
2013-10-25 09:56:54 +00:00
''' Open a survey in edition view '''
2013-10-21 09:03:19 +00:00
id = ids [ 0 ]
context . update ( {
' survey_id ' : id ,
' edit ' : True ,
' ir_actions_act_window_target ' : ' new ' ,
} )
2012-10-11 09:36:46 +00:00
return {
' view_type ' : ' form ' ,
' view_mode ' : ' form ' ,
' res_model ' : ' survey.question.wiz ' ,
' type ' : ' ir.actions.act_window ' ,
' target ' : ' new ' ,
2013-10-21 09:03:19 +00:00
' name ' : self . browse ( cr , uid , id , context = context ) . title ,
2012-10-11 09:36:46 +00:00
' context ' : context
}
2013-10-25 09:56:54 +00:00
def action_send_survey ( self , cr , uid , ids , context = None ) :
''' Open a window to compose an email, pre-filled with the survey
message '''
self . _empty_check ( cr , uid , ids , context = context )
2013-10-21 09:03:19 +00:00
2013-10-25 09:56:54 +00:00
survey_browse = self . pool . get ( ' survey.survey ' ) . browse ( cr , uid , ids ,
context = context ) [ 0 ]
2013-10-21 09:03:19 +00:00
if survey_browse . state != " open " :
2013-10-25 09:56:54 +00:00
raise osv . except_osv ( _ ( ' Warning! ' ) ,
_ ( " You cannot send invitations since the survey is not open. " ) )
2013-10-21 09:03:19 +00:00
2013-10-25 09:56:54 +00:00
assert len ( ids ) == 1 , ' This option should only be used for a single \
survey at a time . '
2013-10-21 09:03:19 +00:00
ir_model_data = self . pool . get ( ' ir.model.data ' )
try :
2013-10-28 07:51:21 +00:00
template_id = ir_model_data . get_object_reference ( cr , uid ,
' survey.survey ' , ' email_template_survey ' ) [ 1 ]
2013-10-21 09:03:19 +00:00
except ValueError :
template_id = False
ctx = dict ( context )
ctx . update ( {
2013-10-25 09:56:54 +00:00
' default_model ' : ' survey.survey ' ,
2013-10-21 09:03:19 +00:00
' default_res_id ' : ids [ 0 ] ,
' default_survey_id ' : ids [ 0 ] ,
' default_use_template ' : bool ( template_id ) ,
' default_template_id ' : template_id ,
' default_composition_mode ' : ' comment ' ,
' survey_state ' : survey_browse . state
} )
2012-08-21 05:36:25 +00:00
return {
2013-10-21 09:03:19 +00:00
' type ' : ' ir.actions.act_window ' ,
2012-08-21 05:36:25 +00:00
' view_type ' : ' form ' ,
' view_mode ' : ' form ' ,
2013-10-21 09:03:19 +00:00
' res_model ' : ' survey.mail.compose.message ' ,
2012-08-21 05:36:25 +00:00
' target ' : ' new ' ,
2013-10-21 09:03:19 +00:00
' context ' : ctx ,
2012-04-17 05:50:10 +00:00
}
2012-10-11 09:36:46 +00:00
2013-10-28 16:15:31 +00:00
# def unlink(self, cr, uid, ids, context=None):
# ''' Delete survey and linked email templates (if any) '''
# email_template_ids = list()
# for survey in self.browse(cr, uid, ids, context=context):
# email_template_ids.append(survey.email_template_id.id)
# if email_template_ids:
# self.pool.get('email.template').unlink(cr, uid, email_template_ids,
# context=context)
# return super(survey_survey, self).unlink(cr, uid, ids, context=context)
2010-01-20 14:28:28 +00:00
class survey_page ( osv . osv ) :
2013-10-23 12:22:55 +00:00
''' A page for a survey.
Pages are essentially containers , allowing to group questions by ordered
screens .
2013-10-28 07:51:21 +00:00
. . note : :
2013-10-28 14:43:14 +00:00
A page should be deleted if the survey it belongs to is deleted . '''
2013-10-23 12:22:55 +00:00
2010-01-20 14:28:28 +00:00
_name = ' survey.page '
2013-10-23 12:22:55 +00:00
_description = ' Survey Page '
2010-01-20 14:28:28 +00:00
_rec_name = ' title '
_order = ' sequence '
2013-10-23 12:22:55 +00:00
# Model Fields #
2010-01-20 14:28:28 +00:00
_columns = {
2013-10-23 12:22:55 +00:00
' title ' : fields . char ( ' Page Title ' , size = 128 , required = 1 ,
translate = True ) ,
' survey_id ' : fields . many2one ( ' survey.survey ' , ' Survey ' ,
ondelete = ' cascade ' ) ,
' question_ids ' : fields . one2many ( ' survey.question ' , ' page_id ' ,
' Questions ' ) ,
' sequence ' : fields . integer ( ' Page number ' ) ,
' description ' : fields . text ( ' Description ' ,
help = " An introductory text to your page " , translate = True ,
oldname = " note " ) ,
2010-01-20 14:28:28 +00:00
}
_defaults = {
2013-10-21 09:03:19 +00:00
' sequence ' : 1
2010-01-20 14:28:28 +00:00
}
2013-10-23 12:22:55 +00:00
# Public methods #
2010-11-22 10:37:53 +00:00
def survey_save ( self , cr , uid , ids , context = None ) :
2010-11-23 07:05:05 +00:00
if context is None :
2010-11-22 10:37:53 +00:00
context = { }
2013-10-21 09:03:19 +00:00
surv_name_wiz = self . pool . get ( ' survey.question.wiz ' )
2013-10-23 12:22:55 +00:00
surv_name_wiz . write ( cr , uid , [ context . get ( ' wizard_id ' , False ) ] ,
{ ' transfer ' : True , ' page_no ' : context . get ( ' page_number ' , 0 ) } )
2010-01-20 14:28:28 +00:00
return {
2010-04-06 07:02:31 +00:00
' view_type ' : ' form ' ,
' view_mode ' : ' form ' ,
' res_model ' : ' survey.question.wiz ' ,
' type ' : ' ir.actions.act_window ' ,
' target ' : ' new ' ,
' context ' : context
}
2010-01-20 14:28:28 +00:00
2010-12-14 07:37:12 +00:00
def copy ( self , cr , uid , ids , default = None , context = None ) :
2010-12-09 05:36:29 +00:00
vals = { }
current_rec = self . read ( cr , uid , ids , context = context )
2012-09-24 16:26:45 +00:00
title = _ ( " %s (copy) " ) % ( current_rec . get ( ' title ' ) )
2013-10-21 09:03:19 +00:00
vals . update ( { ' title ' : title } )
2013-10-23 12:22:55 +00:00
return super ( survey_page , self ) . copy ( cr , uid , ids , vals ,
context = context )
2010-02-05 11:25:40 +00:00
2010-01-20 14:28:28 +00:00
class survey_question ( osv . osv ) :
2013-10-23 12:22:55 +00:00
''' Questions that will be asked in a survey.
2013-10-28 14:43:14 +00:00
Each question can have one of more suggested answers ( eg . in case of
dropdown choices , multi - answer checkboxes , radio buttons . . . )
2013-10-28 07:51:21 +00:00
Changes
- - - - - - -
2013-10-23 12:22:55 +00:00
This version of the model has been simplified in relation to the previous
one : some fields were simply a n - time repetition of a simpler field . It is
2013-10-24 09:26:33 +00:00
now allowed to have children question that allows to group subquestions . '''
2010-01-20 14:28:28 +00:00
_name = ' survey.question '
2013-10-23 12:22:55 +00:00
_description = ' Question '
2010-01-20 14:28:28 +00:00
_rec_name = ' question '
_order = ' sequence '
2013-10-23 12:22:55 +00:00
# Model fields #
2010-01-20 14:28:28 +00:00
_columns = {
2013-10-24 09:26:33 +00:00
# Question metadata
2013-10-23 12:22:55 +00:00
' page_id ' : fields . many2one ( ' survey.page ' , ' Survey page ' ,
ondelete = ' cascade ' ) ,
' survey_id ' : fields . related ( ' page_id ' , ' survey_id ' , type = ' many2one ' ,
relation = ' survey.survey ' , string = ' Survey ' , store = True ) ,
' parent_id ' : fields . many2one ( ' survey.question ' , ' Parent question ' ) ,
2013-10-29 16:20:34 +00:00
' children_ids ' : fields . one2many ( ' survey.question ' , ' parent_id ' ,
2013-10-23 12:22:55 +00:00
' Children questions ' ) ,
2013-10-24 09:26:33 +00:00
' sequence ' : fields . integer ( ' Sequence ' ) ,
2013-10-23 12:22:55 +00:00
2013-10-24 09:26:33 +00:00
# Question
' question ' : fields . char ( ' Question ' , required = 1 , translate = True ) ,
' description ' : fields . text ( ' Description ' , help = " Use this field to add \
2013-10-29 15:17:31 +00:00
additional explanations about your question " , translate=True,
oldname = ' descriptive_text ' ) ,
2013-10-24 14:56:39 +00:00
' display ' : fields . selection (
[ ( ' horizontal ' , ' Horizontal ' ) ,
( ' vertical ' , ' Vertical ' ) ] ,
' Display ' ) ,
2013-10-23 12:22:55 +00:00
2013-10-24 09:26:33 +00:00
# Answer
2013-10-31 08:08:56 +00:00
' type ' : fields . selection ( [ ( ' free_text ' , ' Free Text ' ) ,
( ' textbox ' , ' Text box ' ) ,
2013-10-24 09:26:33 +00:00
( ' numerical_box ' , ' Numerical box ' ) ,
2013-10-23 12:22:55 +00:00
( ' datetime ' , ' Date and Time ' ) ,
( ' checkbox ' , ' Checkbox ' ) ,
2013-10-24 09:26:33 +00:00
( ' simple_choice_scale ' , ' One choice on a scale ' ) ,
( ' simple_choice_dropdown ' , ' One choice in a menu ' ) ,
( ' multiple_choice ' , ' Some choices in checkboxes ' ) ,
2013-10-31 08:08:56 +00:00
( ' vector ' , ' Multi-questions ' ) ,
( ' matrix ' , ' Matrix ' )
2013-10-24 14:56:39 +00:00
] , ' Question Type ' , required = 1 ) ,
2013-10-29 15:17:31 +00:00
' suggested_answers_ids ' : fields . one2many ( ' survey.suggestion ' ,
' question_id ' , ' Suggested answers ' , oldname = ' answer_choice_ids ' ) ,
2013-10-24 14:56:39 +00:00
# Comments
' comments_allowed ' : fields . boolean ( ' Allow comments ' ,
oldname = " allow_comment " ) ,
' comment_children_ids ' : fields . one2many ( ' survey.question_id ' ,
' parent_id ' , ' Comment question ' ) , # one2one in fact
' comment_count_as_answer ' : fields . boolean ( ' Make Comment Field an \
Answer Choice ' , oldname= ' make_comment_field ' ),
# Validation
' validation_required ' : fields . boolean ( ' Validate entry ' ,
oldname = ' is_validation_require ' ) ,
' validation_type ' : fields . selection ( [
( ' has_length ' , ' Must Be Specific Length ' ) ,
( ' is_integer ' , ' Must Be A Whole Number ' ) ,
( ' is_decimal ' , ' Must Be A Decimal Number ' ) ,
( ' is_date ' , ' Must Be A Date ' ) ,
( ' is_email ' , ' Must Be An Email Address ' )
] , ' Text Validation ' ) ,
' validation_length ' : fields . integer ( ' Specific length ' ) ,
2013-10-31 08:08:56 +00:00
' validation_min_float_value ' : fields . float ( ' Minimum value ' ) ,
' validation_max_float_value ' : fields . float ( ' Maximum value ' ) ,
' validation_min_int_value ' : fields . integer ( ' Minimum value ' ) ,
' validation_max_int_value ' : fields . integer ( ' Maximum value ' ) ,
2013-10-24 14:56:39 +00:00
' validation_min_date ' : fields . date ( ' Start date range ' ) ,
' validation_max_date ' : fields . date ( ' End date range ' ) ,
2013-10-28 14:43:14 +00:00
' validation_error_msg ' : fields . char ( " Error message if validation \
2013-10-29 15:17:31 +00:00
fails " , oldname= ' validation_valid_err_msg ' ),
2013-10-23 12:22:55 +00:00
2013-10-24 14:56:39 +00:00
' numeric_required_sum ' : fields . integer ( ' Sum of all choices ' ) ,
2013-10-28 14:43:14 +00:00
' numeric_required_sum_err_msg ' : fields . text ( ' Error message ' ,
translate = True ) ,
2013-10-24 14:56:39 +00:00
2013-10-28 16:15:31 +00:00
# 'in_visible_rating_weight': fields.boolean('Is Rating Scale nvisible?'),
# 'in_visible_menu_choice': fields.boolean('Is Menu Choice Invisible?'),
# 'in_visible_answer_type': fields.boolean('Is Answer Type Invisible?'),
# 'comment_column': fields.boolean('Add comment column in matrix'),
# 'column_name': fields.char('Column Name', translate=True),
# 'no_of_rows': fields.integer('No of Rows'),
2013-10-24 09:26:33 +00:00
2013-10-24 14:56:39 +00:00
# Constraints on number of answers
2013-10-24 09:26:33 +00:00
' constr_mandatory ' : fields . boolean ( ' Mandatory question ' ,
oldname = " is_require_answer " ) ,
' constr_type ' : fields . selection ( [ ( ' all ' , ' All ' ) ,
( ' at least ' , ' At Least ' ) ,
( ' at most ' , ' At Most ' ) ,
( ' exactly ' , ' Exactly ' ) ,
( ' a range ' , ' A Range ' ) ] ,
2013-10-29 15:17:31 +00:00
' Constraint on answers number ' , oldname = ' required_type ' ) ,
' constr_maximum_req_ans ' : fields . integer ( ' Maximum Required Answer ' ,
oldname = ' maximum_req_ans ' ) ,
' constr_minimum_req_ans ' : fields . integer ( ' Minimum Required Answer ' ,
oldname = ' minimum_req_ans ' ) ,
' constr_error_msg ' : fields . char ( " Error message if constraints fails " ,
oldname = ' req_error_msg ' ) ,
2010-01-20 14:28:28 +00:00
}
_defaults = {
2013-10-21 09:03:19 +00:00
' sequence ' : 1 ,
' page_id ' : lambda s , cr , uid , c : c . get ( ' page_id ' ) ,
2013-10-24 14:56:39 +00:00
' type ' : lambda s , cr , uid , c : _ ( ' multiple_choice ' ) ,
2013-10-28 07:51:21 +00:00
#'req_error_msg': lambda s, cr, uid, c: _('This question requires an answer.'),
2013-10-29 15:17:31 +00:00
' constr_type ' : ' at least ' ,
' constr_minimum_req_ans ' : 1 ,
2013-10-28 07:51:21 +00:00
#'comment_field_type': 'char',
#'comment_label': lambda s, cr, uid, c: _('Other (please specify)'),
#'comment_valid_type': 'do_not_validate',
#'comment_valid_err_msg': lambda s, cr, uid, c: _('The comment you entered is in an invalid format.'),
2013-10-31 08:08:56 +00:00
' validation_required ' : ' False ' ,
2013-10-28 07:51:21 +00:00
#'validation_valid_err_msg': lambda s, cr, uid, c: _('The comment you entered is in an invalid format.'),
#'numeric_required_sum_err_msg': lambda s, cr, uid, c: _('The choices need to add up to [enter sum here].'),
#'make_comment_field_err_msg': lambda s, cr, uid, c: _('Please enter a comment.'),
#'in_visible_answer_type': 1
2010-01-20 14:28:28 +00:00
}
2013-10-28 16:15:31 +00:00
def on_change_type ( self , cr , uid , ids , type , context = None ) :
''' Updates the editing view in relation with the question type '''
2010-02-05 09:48:02 +00:00
val = { }
val [ ' is_require_answer ' ] = False
val [ ' is_comment_require ' ] = False
val [ ' is_validation_require ' ] = False
val [ ' comment_column ' ] = False
2010-03-15 10:52:27 +00:00
2010-02-04 10:20:01 +00:00
if type in [ ' multiple_textboxes_diff_type ' ] :
2010-02-05 09:48:02 +00:00
val [ ' in_visible_answer_type ' ] = False
return { ' value ' : val }
2010-03-15 10:52:27 +00:00
2010-01-20 14:28:28 +00:00
if type in [ ' rating_scale ' ] :
2013-10-28 16:15:31 +00:00
val . update ( { ' in_visible_rating_weight ' : False ,
' in_visible_menu_choice ' : True } )
2010-02-05 09:48:02 +00:00
return { ' value ' : val }
2010-03-15 10:52:27 +00:00
2010-01-20 14:28:28 +00:00
elif type in [ ' single_textbox ' ] :
2013-10-28 16:15:31 +00:00
val . update ( { ' in_visible_rating_weight ' : True ,
' in_visible_menu_choice ' : True } )
2010-02-05 09:48:02 +00:00
return { ' value ' : val }
2010-03-15 10:52:27 +00:00
2010-01-20 14:28:28 +00:00
else :
2013-10-28 16:15:31 +00:00
val . update ( { ' in_visible_rating_weight ' : True ,
' in_visible_menu_choice ' : True ,
' in_visible_answer_type ' : True } )
2010-02-05 09:48:02 +00:00
return { ' value ' : val }
2010-01-20 14:28:28 +00:00
2013-10-21 09:03:19 +00:00
def on_change_page_id ( self , cr , uid , ids , page_id , context = None ) :
if page_id :
2013-10-28 16:15:31 +00:00
page = self . pool . get ( ' survey.page ' ) . browse ( cr , uid , page_id ,
context = context )
2013-10-21 09:03:19 +00:00
return { ' survey_id ' : page . survey_id and page . survey_id . id }
return { ' value ' : { } }
2010-01-20 14:28:28 +00:00
def write ( self , cr , uid , ids , vals , context = None ) :
2013-10-23 09:03:42 +00:00
questions = self . read ( cr , uid , ids , [ ' answer_choice_ids ' , ' type ' ,
2013-10-22 15:10:51 +00:00
' required_type ' , ' req_ans ' , ' minimum_req_ans ' , ' maximum_req_ans ' ,
' column_heading_ids ' , ' page_id ' , ' question ' ] )
2010-01-20 14:28:28 +00:00
for question in questions :
col_len = len ( question [ ' column_heading_ids ' ] )
2013-10-21 09:03:19 +00:00
for col in vals . get ( ' column_heading_ids ' , [ ] ) :
if type ( col [ 2 ] ) == type ( { } ) :
col_len + = 1
else :
col_len - = 1
2010-03-15 10:52:27 +00:00
2013-10-21 09:03:19 +00:00
que_type = vals . get ( ' type ' , question [ ' type ' ] )
2010-03-15 10:52:27 +00:00
2013-10-21 09:03:19 +00:00
if que_type in [ ' matrix_of_choices_only_one_ans ' , ' matrix_of_choices_only_multi_ans ' , ' rating_scale ' ] :
2010-01-20 14:28:28 +00:00
if not col_len :
2013-10-21 09:03:19 +00:00
raise osv . except_osv ( _ ( ' Warning! ' ) , _ ( ' You must enter one or more column headings for question " %s " of page %s . ' ) % ( question [ ' question ' ] , question [ ' page_id ' ] [ 1 ] ) )
2010-01-20 14:28:28 +00:00
ans_len = len ( question [ ' answer_choice_ids ' ] )
2010-03-15 10:52:27 +00:00
2013-10-21 09:03:19 +00:00
for ans in vals . get ( ' answer_choice_ids ' , [ ] ) :
if type ( ans [ 2 ] ) == type ( { } ) :
ans_len + = 1
else :
ans_len - = 1
2010-03-15 10:52:27 +00:00
2013-10-21 09:03:19 +00:00
if que_type not in [ ' descriptive_text ' , ' single_textbox ' , ' comment ' , ' table ' ] :
2010-01-20 14:28:28 +00:00
if not ans_len :
2013-10-21 09:03:19 +00:00
raise osv . except_osv ( _ ( ' Warning! ' ) , _ ( ' You must enter one or more Answers for question " %s " of page %s . ' ) % ( question [ ' question ' ] , question [ ' page_id ' ] [ 1 ] ) )
2010-03-15 10:52:27 +00:00
2013-10-21 09:03:19 +00:00
req_type = vals . get ( ' required_type ' , question [ ' required_type ' ] )
2010-03-15 10:52:27 +00:00
2013-10-21 09:03:19 +00:00
if que_type in [ ' multiple_choice_multiple_ans ' , ' matrix_of_choices_only_one_ans ' , \
' matrix_of_choices_only_multi_ans ' , ' rating_scale ' , ' multiple_textboxes ' , \
' numerical_textboxes ' , ' date ' , ' date_and_time ' ] :
2010-01-27 13:55:23 +00:00
if req_type in [ ' at least ' , ' at most ' , ' exactly ' ] :
2013-10-21 09:03:19 +00:00
if ' req_ans ' in vals :
if not vals [ ' req_ans ' ] or vals [ ' req_ans ' ] > ans_len :
raise osv . except_osv ( _ ( ' Warning! ' ) , _ ( " #Required Answer you entered \
2010-03-26 13:27:16 +00:00
is greater than the number of answer . \
Please use a number that is smaller than % d . " ) % (ans_len + 1))
2010-01-27 13:55:23 +00:00
else :
2013-10-21 09:03:19 +00:00
if not question [ ' req_ans ' ] or question [ ' req_ans ' ] > ans_len :
raise osv . except_osv ( _ ( ' Warning! ' ) , _ ( " #Required Answer you entered is \
2010-03-26 13:27:16 +00:00
greater than the number of answer . \
Please use a number that is smaller than % d . " ) % (ans_len + 1))
2010-03-15 10:52:27 +00:00
2010-01-27 13:55:23 +00:00
if req_type == ' a range ' :
minimum_ans = 0
maximum_ans = 0
2013-10-21 09:03:19 +00:00
minimum_ans = ' minimum_req_ans ' in vals and vals [ ' minimum_req_ans ' ] or question [ ' minimum_req_ans ' ]
maximum_ans = ' maximum_req_ans ' in vals and vals [ ' maximum_req_ans ' ] or question [ ' maximum_req_ans ' ]
if not minimum_ans or minimum_ans > ans_len or not maximum_ans or maximum_ans > ans_len :
raise osv . except_osv ( _ ( ' Warning! ' ) , _ ( " Minimum Required Answer you \
entered is greater than the number of answer . \
Please use a number that is smaller than % d . " ) % (ans_len + 1))
2010-01-27 13:55:23 +00:00
if maximum_ans < = minimum_ans :
2013-10-21 09:03:19 +00:00
raise osv . except_osv ( _ ( ' Warning! ' ) , _ ( " Maximum Required Answer is greater \
2010-03-26 13:27:16 +00:00
than Minimum Required Answer " ))
2010-03-15 10:52:27 +00:00
2010-01-20 14:28:28 +00:00
return super ( survey_question , self ) . write ( cr , uid , ids , vals , context = context )
2010-11-22 10:37:53 +00:00
def create ( self , cr , uid , vals , context = None ) :
2013-10-21 09:03:19 +00:00
page = self . pool . get ( ' survey.page ' ) . browse ( cr , uid , ' page_id ' in vals and vals [ ' page_id ' ] or context [ ' page_id ' ] , context = context )
if ' answer_choice_ids ' in vals and not len ( vals . get ( ' answer_choice_ids ' , [ ] ) ) and \
vals . get ( ' type ' ) not in [ ' descriptive_text ' , ' single_textbox ' , ' comment ' , ' table ' ] :
raise osv . except_osv ( _ ( ' Warning! ' ) , _ ( ' You must enter one or more answers for question " %s " of page %s . ' ) % ( vals [ ' question ' ] , page . title ) )
if ' column_heading_ids ' in vals and not len ( vals . get ( ' column_heading_ids ' , [ ] ) ) and \
vals . get ( ' type ' ) in [ ' matrix_of_choices_only_one_ans ' , ' matrix_of_choices_only_multi_ans ' , ' rating_scale ' ] :
raise osv . except_osv ( _ ( ' Warning! ' ) , _ ( ' You must enter one or more column headings for question " %s " of page %s . ' ) % ( vals [ ' question ' ] , page . title ) )
if ' is_require_answer ' in vals and vals . get ( ' type ' ) in [ ' multiple_choice_multiple_ans ' , ' matrix_of_choices_only_one_ans ' , \
' matrix_of_choices_only_multi_ans ' , ' rating_scale ' , ' multiple_textboxes ' , ' numerical_textboxes ' , ' date ' , ' date_and_time ' ] :
if vals . get ( ' required_type ' ) in [ ' at least ' , ' at most ' , ' exactly ' ] :
if ' answer_choice_ids ' in vals and ' answer_choice_ids ' in vals and vals . get ( ' req_ans ' ) > len ( vals . get ( ' answer_choice_ids ' , [ ] ) ) :
raise osv . except_osv ( _ ( ' Warning! ' ) , _ ( " #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 ) )
if vals . get ( ' required_type ' ) == ' a range ' :
if ' answer_choice_ids ' in vals :
if not vals . get ( ' minimum_req_ans ' ) or vals [ ' minimum_req_ans ' ] > len ( vals [ ' answer_choice_ids ' ] ) :
raise osv . except_osv ( _ ( ' Warning! ' ) , _ ( " 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 ) )
if not vals . get ( ' maximum_req_ans ' ) or vals [ ' maximum_req_ans ' ] > len ( vals [ ' answer_choice_ids ' ] ) :
raise osv . except_osv ( _ ( ' Warning! ' ) , _ ( " 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 ) )
if vals . get ( ' maximum_req_ans ' , 0 ) < = vals . get ( ' minimum_req_ans ' , 0 ) :
raise osv . except_osv ( _ ( ' Warning! ' ) , _ ( " Maximum Required Answer is greater than Minimum Required Answer. " ) )
return super ( survey_question , self ) . create ( cr , uid , vals , context )
2010-01-20 14:28:28 +00:00
2010-11-22 10:37:53 +00:00
def survey_save ( self , cr , uid , ids , context = None ) :
2010-11-23 07:05:05 +00:00
if context is None :
2010-11-22 10:37:53 +00:00
context = { }
2013-10-21 09:03:19 +00:00
surv_name_wiz = self . pool . get ( ' survey.question.wiz ' )
2013-10-28 16:15:31 +00:00
surv_name_wiz . write ( cr , uid , [ context . get ( ' wizard_id ' , False ) ] ,
{ ' transfer ' : True , ' page_no ' : context . get ( ' page_number ' , False ) } )
2010-01-20 14:28:28 +00:00
return {
2010-04-06 07:02:31 +00:00
' view_type ' : ' form ' ,
' view_mode ' : ' form ' ,
' res_model ' : ' survey.question.wiz ' ,
' type ' : ' ir.actions.act_window ' ,
' target ' : ' new ' ,
' context ' : context
}
2010-01-20 14:28:28 +00:00
2013-10-28 14:43:14 +00:00
class survey_suggestion ( osv . osv ) :
''' A suggested answer for a question '''
_name = ' survey.suggestion '
_rec_name = ' value '
_columns = {
2013-10-29 16:20:34 +00:00
#'survey_id': fields.related('page_id', 'survey_id', type='many2one',
# relation='survey.survey', string='Survey', store=True),
2013-10-28 14:43:14 +00:00
' question_id ' : fields . many2one ( ' survey.question ' , ' Question ' ,
required = True , ondelete = ' cascade ' ) ,
2013-10-28 16:15:31 +00:00
' value ' : fields . char ( " Suggested value " , length = 128 , translate = True ,
required = True )
2013-10-28 14:43:14 +00:00
}
2013-10-23 12:22:55 +00:00
class survey_user_input ( osv . osv ) :
2013-10-24 09:26:33 +00:00
''' Metadata for a set of one user ' s answers to a particular survey '''
2013-10-23 12:22:55 +00:00
_name = " survey.user_input "
2010-01-20 14:28:28 +00:00
_rec_name = ' date_create '
2013-10-21 09:03:19 +00:00
2010-01-20 14:28:28 +00:00
_columns = {
2013-10-28 07:51:21 +00:00
' survey_id ' : fields . many2one ( ' survey.survey ' , ' Survey ' , required = True ,
2013-10-24 09:26:33 +00:00
readonly = 1 , ondelete = ' restrict ' ) ,
2013-10-25 09:56:54 +00:00
' date_create ' : fields . datetime ( ' Creation Date ' , required = True ,
2013-10-24 09:26:33 +00:00
readonly = 1 ) ,
' deadline ' : fields . date ( " Deadline " ,
help = " Date by which the person can take part to the survey " ,
oldname = " date_deadline " ) ,
' type ' : fields . selection ( [ ( ' manually ' , ' Manually ' ) , ( ' link ' , ' Link ' ) ] ,
' Answer Type ' , required = 1 , oldname = " response_type " ) ,
' state ' : fields . selection ( [ ( ' new ' , ' Not started yet ' ) ,
( ' skip ' , ' Partially completed ' ) ,
( ' done ' , ' Completed ' ) ,
( ' cancel ' , ' Cancelled ' ) ,
( ' test ' , ' Test ' ) ] , ' Status ' ,
readonly = True ) ,
# Optional Identification data
2013-10-29 15:17:31 +00:00
' token ' : fields . char ( " Indentification token " , readonly = 1 , size = 36 ) ,
2013-10-21 09:03:19 +00:00
' partner_id ' : fields . many2one ( ' res.partner ' , ' Partner ' , readonly = 1 ) ,
2013-10-24 09:26:33 +00:00
' email ' : fields . char ( " E-mail " , size = 64 , readonly = 1 ) ,
# The answers !
' user_input_line_ids ' : fields . one2many ( ' survey.user_input.line ' ,
' user_input_id ' , ' Answers ' ) ,
2010-01-28 07:32:59 +00:00
}
_defaults = {
2013-10-29 15:17:31 +00:00
' date_create ' : fields . datetime . now ,
2013-10-24 09:26:33 +00:00
' type ' : ' manually ' ,
' state ' : ' new ' ,
2013-10-29 15:17:31 +00:00
' token ' : lambda s , cr , uid , c : uuid . uuid4 ( ) . __str__ ( ) ,
2010-01-20 14:28:28 +00:00
}
[IMP]:survey,crm_hr,hr_evaluation.(Ref-YSA,APA)
-Rename Defination into Definition.
-When you click on test, answer or edit survey, remove the first screen with the selection box to select the survey.
-Add survey Types in demo data: Human Resources, Customer Feeback, Supplier Selection.
-In search view of surveys, remove the vertical separator between draft and open buttons, for type field set widget=selection.
-The button for responsible=my in the search view must be default="1".
-change demo data so that some surveys belongs to admin and some to demo user.
-The browse Response report must be renamed into "Print Answers".
-Browse the answer in the screen instead of printing a PDF.
-In the history one2many, first put the date and then the user.
-I started a survey but did not finished it. so that's normal but I was not able to restart the survey (it says I already answered).
-Removed the "Que: " prefix in each report.
bzr revid: apa@tinyerp.com-20100223093223-vwhgkn8kmdo8e6mo
2010-02-23 09:32:23 +00:00
2013-10-21 09:03:19 +00:00
def action_survey_resent ( self , cr , uid , ids , context = None ) :
record = self . browse ( cr , uid , ids [ 0 ] , context = context )
context = context or { }
context . update ( {
' survey_resent_token ' : True ,
' default_partner_ids ' : record . partner_id and [ record . partner_id . id ] or [ ] ,
' default_multi_email ' : record . email or " " ,
' default_public ' : ' email_private ' ,
} )
2013-10-28 16:15:31 +00:00
return self . pool . get ( ' survey.survey ' ) . action_survey_sent ( cr , uid ,
[ record . survey_id . id ] , context = context )
2013-10-21 09:03:19 +00:00
def action_print_response ( self , cr , uid , ids , context = None ) :
"""
Print Survey Answer in pdf format .
@return : Dictionary value for created survey answer report
"""
return {
' type ' : ' ir.actions.report.xml ' ,
' report_name ' : ' survey.browse.response ' ,
' datas ' : {
' model ' : ' survey.print.statistics ' ,
' form ' : {
2013-10-28 16:15:31 +00:00
' response_ids ' : ids ,
' orientation ' : ' vertical ' ,
' paper_size ' : ' letter ' ,
' page_number ' : 0 ,
' without_pagebreak ' : 0
2013-10-21 09:03:19 +00:00
}
} ,
}
def action_preview ( self , cr , uid , ids , context = None ) :
"""
Get preview response
"""
context = context or { }
2013-10-28 07:51:21 +00:00
self . pool . get ( ' survey.survey ' ) . check_access_rights ( cr , uid , ' write ' )
2013-10-21 09:03:19 +00:00
record = self . browse ( cr , uid , ids [ 0 ] , context = context )
context . update ( {
' ir_actions_act_window_target ' : ' new ' ,
' survey_id ' : record . survey_id . id ,
' response_id ' : ids [ 0 ] ,
' readonly ' : True ,
} )
return {
' view_type ' : ' form ' ,
" view_mode " : ' form ' ,
' res_model ' : ' survey.question.wiz ' ,
' type ' : ' ir.actions.act_window ' ,
' target ' : ' new ' ,
' context ' : context
}
def action_cancel ( self , cr , uid , ids , context = None ) :
2013-10-28 07:51:21 +00:00
self . pool . get ( ' survey.survey ' ) . check_access_rights ( cr , uid , ' write ' )
2013-10-21 09:03:19 +00:00
return self . write ( cr , uid , ids , { ' state ' : ' cancel ' } )
2010-03-04 09:16:44 +00:00
def name_get ( self , cr , uid , ids , context = None ) :
if not len ( ids ) :
return [ ]
2013-10-28 16:15:31 +00:00
reads = self . read ( cr , uid , ids , [ ' partner_id ' , ' date_create ' ] ,
context = context )
2010-03-04 09:16:44 +00:00
res = [ ]
for record in reads :
2013-10-21 09:03:19 +00:00
name = ( record [ ' partner_id ' ] and record [ ' partner_id ' ] [ 1 ] or ' ' ) + ' ( ' + record [ ' date_create ' ] . split ( ' . ' ) [ 0 ] + ' ) '
2010-03-04 09:16:44 +00:00
res . append ( ( record [ ' id ' ] , name ) )
return res
2010-11-23 11:31:52 +00:00
def copy ( self , cr , uid , id , default = None , context = None ) :
2013-10-28 16:15:31 +00:00
raise osv . except_osv ( _ ( ' Warning! ' ) , _ ( ' You cannot duplicate this \
element ! ' ))
2013-10-23 09:03:42 +00:00
2010-01-20 14:28:28 +00:00
2013-10-24 09:26:33 +00:00
class survey_user_input_line ( osv . osv ) :
_name = ' survey.user_input.line '
_description = ' User input line '
2010-01-20 14:28:28 +00:00
_rec_name = ' date_create '
_columns = {
2013-10-28 07:51:21 +00:00
' survey_id ' : fields . many2one ( ' survey.survey ' , ' Survey ' , required = 1 ,
2013-10-24 09:26:33 +00:00
readonly = 1 , ondelete = ' cascade ' ) ,
' user_input_id ' : fields . many2one ( ' survey.user_input ' , ' User Input ' ,
2013-10-28 07:51:21 +00:00
ondelete = ' cascade ' , required = 1 ) ,
2013-10-22 15:10:51 +00:00
' date_create ' : fields . datetime ( ' Create Date ' , required = 1 ) , # drop
2013-10-24 09:26:33 +00:00
' skipped ' : fields . boolean ( ' Skipped ' ) ,
' question_id ' : fields . many2one ( ' survey.question ' , ' Question ' ,
ondelete = ' restrict ' ) ,
2013-10-28 14:43:14 +00:00
' answer_type ' : fields . selection ( [ ( ' textbox ' , ' Text box ' ) ,
2013-10-25 09:56:54 +00:00
( ' numerical_box ' , ' Numerical box ' ) ,
( ' free_text ' , ' Free Text ' ) ,
( ' datetime ' , ' Date and Time ' ) ,
( ' checkbox ' , ' Checkbox ' ) ,
] , ' Question Type ' , required = 1 ) ,
2013-10-28 14:43:14 +00:00
' value_text ' : fields . char ( " Text answer " ) ,
' value_number ' : fields . float ( " Numerical answer " ) ,
' value_date ' : fields . datetime ( " Date answer " ) ,
' value_free_text ' : fields . text ( " Free Text answer " ) ,
' value_suggested ' : fields . many2one ( ' survey.suggestion ' ) ,
2013-10-24 09:26:33 +00:00
}
_defaults = {
' skipped ' : False ,
2013-10-29 15:17:31 +00:00
' date_create ' : fields . datetime . now
2010-01-20 14:28:28 +00:00
}
2013-10-21 09:03:19 +00:00
# vim: exp and tab: smartindent: tabstop=4: softtabstop=4: shiftwidth=4: