1 # -*- encoding: utf-8 -*-
2 ##############################################################################
4 # OpenERP, Open Source Management Solution
5 # Copyright (C) 2004-2009 Tiny SPRL (<http://tiny.be>).
7 # This program is free software: you can redistribute it and/or modify
8 # it under the terms of the GNU Affero General Public License as
9 # published by the Free Software Foundation, either version 3 of the
10 # License, or (at your option) any later version.
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 # GNU Affero General Public License for more details.
17 # You should have received a copy of the GNU Affero General Public License
18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
20 ##############################################################################
23 from osv import fields, osv
24 from mx import DateTime as dt
26 from tools.translate import _
28 class hr_evaluation_plan(osv.osv):
29 _name = "hr_evaluation.plan"
30 _description = "Evaluation Plan"
32 'name': fields.char("Evaluation Plan", size=64, required=True),
33 'company_id': fields.many2one('res.company', 'Company', required=True),
34 'phase_ids' : fields.one2many('hr_evaluation.plan.phase', 'plan_id', 'Evaluation Phases'),
35 'month_first': fields.integer('First Evaluation After'),
36 'month_next': fields.integer('Next Evaluation After'),
37 'active': fields.boolean('Active')
40 'active' : lambda *a: True,
44 class hr_evaluation_plan_phase(osv.osv):
45 _name = "hr_evaluation.plan.phase"
46 _description = "Evaluation Plan Phase"
49 'name': fields.char("Phase", size=64, required=True),
50 'sequence': fields.integer("Sequence"),
51 'company_id': fields.related('plan_id','company_id',type='many2one',relation='res.company',string='Company',store=True),
52 'plan_id': fields.many2one('hr_evaluation.plan','Evaluation Plan', required=True, ondelete='cascade'),
53 'action': fields.selection([
54 ('top-down','Top-Down Appraisal Requests'),
55 ('bottom-up','Bottom-Up Appraisal Requests'),
56 ('self','Self Appraisal Requests'),
57 ('final','Final Interview')], 'Action', required=True),
58 'survey_id': fields.many2one('survey','Appraisal Form',required=True),
59 'send_answer_manager': fields.boolean('All Answers',
60 help="Send all answers to the manager"),
61 'send_answer_employee': fields.boolean('All Answers',
62 help="Send all answers to the employee"),
63 'send_anonymous_manager': fields.boolean('Anonymous Summary',
64 help="Send an anonymous summary to the manager"),
65 'send_anonymous_employee': fields.boolean('Anonymous Summary',
66 help="Send an anonymous summary to the employee"),
67 'wait': fields.boolean('Wait Previous Phases',
68 help="Check this box if you want to wait that all preceeding phases " +
69 "are finished before launching this phase.")
73 'sequence' : lambda *a: 1,
75 hr_evaluation_plan_phase()
77 class hr_employee(osv.osv):
78 _inherit="hr.employee"
80 'evaluation_plan_id': fields.many2one('hr_evaluation.plan', 'Evaluation Plan'),
81 'evaluation_date': fields.date('Next Evaluation', help="Date of the next evaluation"),
84 def onchange_evaluation_plan_id(self,cr,uid,ids,evaluation_plan_id,context={}):
85 evaluation_date = self.browse(cr, uid, ids)[0].evaluation_date or ''
86 evaluation_plan_obj=self.pool.get('hr_evaluation.plan')
87 if evaluation_plan_id:
88 for evaluation_plan in evaluation_plan_obj.browse(cr,uid,[evaluation_plan_id]):
89 if not evaluation_date:
90 evaluation_date=(dt.ISO.ParseAny(dt.now().strftime('%Y-%m-%d'))+ dt.RelativeDateTime(months=+evaluation_plan.month_first)).strftime('%Y-%m-%d')
92 evaluation_date=(dt.ISO.ParseAny(evaluation_date)+ dt.RelativeDateTime(months=+evaluation_plan.month_next)).strftime('%Y-%m-%d')
93 return {'value': {'evaluation_date':evaluation_date}}
96 class hr_evaluation(osv.osv):
97 _name = "hr_evaluation.evaluation"
98 _description = "Employee Evaluation"
99 _rec_name = 'employee_id'
101 'date': fields.date("Evaluation Deadline", required=True),
102 'employee_id': fields.many2one('hr.employee', "Employee", required=True),
103 'note_summary': fields.text('Evaluation Summary'),
104 'note_action': fields.text('Action Plan',
105 help="If the evaluation does not meet the expectations, you can propose"+
107 'rating': fields.selection([
108 ('0','Significantly bellow expectations'),
109 ('1','Did not meet expectations'),
110 ('2','Meet expectations'),
111 ('3','Exceeds expectations'),
112 ('4','Significantly exceeds expectations'),
113 ], "Overall Rating", help="This is the overall rating on that summarize the evaluation"),
114 'survey_request_ids': fields.one2many('hr.evaluation.interview','evaluation_id','Appraisal Forms'),
115 'plan_id': fields.many2one('hr_evaluation.plan', 'Plan', required=True),
116 'state': fields.selection([
118 ('wait','Plan In Progress'),
119 ('progress','Final Validation'),
121 ('cancel','Cancelled'),
122 ], 'State', required=True,readonly=True),
123 'date_close': fields.date('Ending Date'),
124 'progress' : fields.float("Progress"),
127 'date' : lambda *a: (dt.ISO.ParseAny(dt.now().strftime('%Y-%m-%d')) + dt.RelativeDateTime(months =+ 1)).strftime('%Y-%m-%d'),
128 'state' : lambda *a: 'draft',
131 def onchange_employee_id(self,cr,uid,ids,employee_id,context={}):
132 employee_obj=self.pool.get('hr.employee')
133 evaluation_plan_id=''
135 for employee in employee_obj.browse(cr,uid,[employee_id]):
136 if employee and employee.evaluation_plan_id and employee.evaluation_plan_id.id:
137 evaluation_plan_id=employee.evaluation_plan_id.id
138 employee_ids=employee_obj.search(cr,uid,[('parent_id','=',employee.id)])
139 return {'value': {'plan_id':evaluation_plan_id}}
141 def button_plan_in_progress(self,cr, uid, ids, context):
142 employee_obj = self.pool.get('hr.employee')
143 hr_eval_inter_obj = self.pool.get('hr.evaluation.interview')
144 survey_request_obj = self.pool.get('survey.request')
145 curr_employee=self.browse(cr,uid, ids)[0].employee_id
146 child_employees=employee_obj.browse(cr,uid, employee_obj.search(cr,uid,[('parent_id','=',curr_employee.id)]))
147 manager_employee=curr_employee.parent_id
148 for evaluation in self.browse(cr,uid,ids):
149 if evaluation and evaluation.plan_id:
151 for phase in evaluation.plan_id.phase_ids:
152 if phase.action == "bottom-up":
153 for child in child_employees:
155 user = child.user_id.id
156 id = hr_eval_inter_obj.create(cr, uid, {'evaluation_id':evaluation.id ,'user_id' : user,'survey_id' : phase.survey_id.id, 'user_to_review_id' : child.id, 'date_deadline' :(dt.ISO.ParseAny(dt.now().strftime('%Y-%m-%d')) + dt.RelativeDateTime(months =+ 1)).strftime('%Y-%m-%d')})
158 hr_eval_inter_obj.survey_req_waiting_answer(cr, uid, [id], context)
160 elif phase.action == "top-down":
163 if manager_employee.user_id:
164 user = manager_employee.user_id.id
165 id = hr_eval_inter_obj.create(cr, uid, {'evaluation_id':evaluation.id,'user_id': user ,'survey_id' : phase.survey_id.id, 'user_to_review_id' :manager_employee.id, 'date_deadline' :(dt.ISO.ParseAny(dt.now().strftime('%Y-%m-%d')) + dt.RelativeDateTime(months =+ 1)).strftime('%Y-%m-%d')})
167 hr_eval_inter_obj.survey_req_waiting_answer(cr, uid, [id], context)
169 elif phase.action == "self":
172 if curr_employee.user_id:
173 user = curr_employee.user_id.id
174 id = hr_eval_inter_obj.create(cr, uid, {'evaluation_id':evaluation.id,'user_id' : user, 'survey_id' : phase.survey_id.id, 'user_to_review_id' :curr_employee.id, 'date_deadline' :(dt.ISO.ParseAny(dt.now().strftime('%Y-%m-%d')) + dt.RelativeDateTime(months =+ 1)).strftime('%Y-%m-%d')})
176 hr_eval_inter_obj.survey_req_waiting_answer(cr, uid, [id], context)
178 elif phase.action == "final":
181 if manager_employee.user_id:
182 user = manager_employee.user_id.id
183 id = hr_eval_inter_obj.create(cr, uid, {'evaluation_id':evaluation.id,'user_id' : user, 'survey_id' : phase.survey_id.id, 'user_to_review_id' :manager_employee.id, 'date_deadline' :(dt.ISO.ParseAny(dt.now().strftime('%Y-%m-%d')) + dt.RelativeDateTime(months =+ 1)).strftime('%Y-%m-%d')})
185 hr_eval_inter_obj.survey_req_waiting_answer(cr, uid, [id], context)
187 self.write(cr, uid, evaluation.id, {'survey_request_ids':[[6, 0, apprai_id]]})
188 self.write(cr,uid,ids,{'state':'wait'})
191 def button_final_validation(self,cr, uid, ids, context):
192 self.write(cr,uid,ids,{'state':'progress'})
193 request_obj = self.pool.get('hr.evaluation.interview')
194 for id in self.browse(cr, uid ,ids):
195 if len(id.survey_request_ids) != len(request_obj.search(cr, uid, [('evaluation_id', '=', id.id),('state', '=', 'done')])):
196 raise osv.except_osv(_('Warning !'),_("You cannot change state, because some appraisal in waiting answer or draft state"))
199 def button_done(self,cr, uid, ids, context):
200 self.write(cr,uid,ids,{'state':'done', 'date_close': time.strftime('%Y-%m-%d')})
203 def button_cancel(self,cr, uid, ids, context):
204 self.write(cr,uid,ids,{'state':'cancel'})
209 class survey_request(osv.osv):
210 _inherit="survey.request"
212 'is_evaluation':fields.boolean('Is Evaluation?'),
216 class hr_evaluation_interview(osv.osv):
217 _name='hr.evaluation.interview'
218 _inherits={'survey.request':'request_id'}
219 _description='Evaluation Interview'
222 'request_id': fields.many2one('survey.request','Request_id', ondelete='cascade'),
223 'user_to_review_id': fields.many2one('hr.employee', 'Employee'),
224 'evaluation_id' : fields.many2one('hr_evaluation.evaluation', 'Evaluation'),
227 'is_evaluation': lambda *a: True,
230 def survey_req_waiting_answer(self, cr, uid, ids, context):
231 self.write(cr, uid, ids, { 'state' : 'waiting_answer'})
232 # for id in self.browse(cr, uid, ids):
233 # if id.user_id and id.user_id.address_id and id.user_id.address_id and id.user_id.address_id.email:
234 # msg = " Hello %s, \n\n We are inviting you for %s survey. \n\n Thanks," %(id.user_id.name, id.survey_id.title)
235 # tools.email_send(tools.config['email_from'], [id.user_id.address_id.email],\
236 # 'Invite to fill up Survey', msg)
239 def survey_req_done(self, cr, uid, ids, context):
240 self.write(cr, uid, ids, { 'state' : 'done'})
241 hr_eval_obj = self.pool.get('hr_evaluation.evaluation')
242 for id in self.browse(cr, uid, ids):
246 records = self.pool.get("hr_evaluation.evaluation").browse(cr, uid, [id.evaluation_id.id])[0].survey_request_ids
247 for child in records:
248 if child.state == "draft" :
251 if child.state != "done":
255 if not flag and wating_id:
256 self.survey_req_waiting_answer(cr, uid, [wating_id], context)
257 hr_eval_obj.write(cr, uid, [id.evaluation_id.id], {'progress' :tot_done_req * 100 / len(records)})
260 def survey_req_draft(self, cr, uid, ids, arg):
261 self.write(cr, uid, ids, { 'state' : 'draft'})
264 def survey_req_cancel(self, cr, uid, ids, context):
265 self.write(cr, uid, ids, { 'state' : 'cancel'})
268 hr_evaluation_interview()