# -*- coding: utf-8 -*- from odoo import api, fields, models, _, exceptions, Command from datetime import date class EmployeesAppraisal(models.Model): _name = 'hr.group.employee.appraisal' _inherit = ['mail.thread', 'mail.activity.mixin'] _rec_name = 'name' _description = 'Appraisal' name = fields.Char() date = fields.Date() state = fields.Selection([ ("draft", "Draft"), ("gen_appraisal", "Generate Appraisal"), ("start_appraisal", "Start Appraisal"), ("finish_appraisal", "Direct Manager"), ("hr_approval", "Department Manager"), ("gm_approval", "HR Approval"), ("done", "Done") ], default='draft', tracking=True) # Relational fields department_id = fields.Many2one('hr.department') manager_id = fields.Many2one('hr.employee', related='department_id.manager_id') employee_ids = fields.Many2many('hr.employee') appraisal_id = fields.One2many('hr.employee.appraisal', 'employee_appraisal') appraisal_plan_id = fields.Many2one('appraisal.plan') totals_great_level = fields.Float(compute='fill_totals_great_level', tracking=True) totals_level_achieved = fields.Float(compute='fill_totals_great_level', tracking=True) totals_level_achieved_percentage = fields.Float(compute='fill_totals_great_level', tracking=True) totals_appraisal_result = fields.Many2one('appraisal.result', tracking=True, compute='fill_totals_great_level') company_id = fields.Many2one('res.company', string='Company', default=lambda self: self.env.company) appraisal_type = fields.Selection(selection=[('performance', 'Performance'), ('trial', 'Trial Period'), ('training', 'Training'), ('mission', 'Mission'), ('general', 'General'), ('other', 'Other')], string='Appraisal Type') employee_protest = fields.Boolean( readonly=True ) # Dynamic domain for manager_id @api.onchange('department_id') def manager_domain(self): for item in self: if item.department_id: employee_ids = self.env['hr.employee'].search([]) employee_list = [] # Domain for manager_id if not item.department_id.manager_id: item.manager_id = False for line in employee_ids: if line.department_id: if line.department_id == item.department_id: employee_list.append(line.id) return {'domain': {'manager_id': [('id', 'in', employee_list)]}} # Dynamic domain for employee_ids @api.onchange('department_id') def employee_ids_domain(self): for item in self: if item.department_id: department_ids = self.env['hr.department'].search([]) employee_ids = self.env['hr.employee'].search([]) department_list, employee_list = [], [] # Adding the selected department to department_list department_list.append(item.department_id.id) # Domain for employee_ids for line in department_ids: if line.parent_id: if line.parent_id == item.department_id: department_list.append(line.id) for sub_line in department_ids: if sub_line.parent_id == line: department_list.append(sub_line.id) for line in employee_ids: if line.department_id: if line.department_id.id in department_list: employee_list.append(line.id) if item.department_id: return {'domain': {'employee_ids': [('id', 'in', employee_list)]}} # Create records in hr.employee.appraisal when change state to Generate Appraisal def gen_appraisal(self): for item in self: if item.employee_ids: appraisal_lines = [] # Fill employee appraisal for element in item.employee_ids: standard_appraisal_list, manager_appraisal_list = [], [] if not item.appraisal_plan_id.is_manager: # Fill standard_appraisal_employee_line_ids to complete for line in item.appraisal_plan_id.standard_appraisal_id: standard_appraisal_list.append({ 'great_level': line.great_level, 'question': line.question }) else: # Fill manager_appraisal_line_id to complete for line in item.appraisal_plan_id.manager_appraisal_id: complete_manager_appraisal_list = [] for record in line.question_id.customize_appraisal_id: complete_manager_appraisal_list.append({ 'question': record.question, 'great_degree_level': record.great_degree_level, 'degree_id': record.degree_id.id }) record = self.env['manager.appraisal.complete.line'].create({ 'name': line.question_id.name, 'great_level': line.great_level, 'customize_appraisal_id': [Command.create(value) for value in complete_manager_appraisal_list] }) manager_appraisal_list.append({ 'appraisal_name': line.appraisal_name, 'question_id': line.question_id.id, 'question_complete_id': record.id }) appraisal_line = { 'employee_id': element.id, 'appraisal_date': date.today(), 'is_manager': item.appraisal_plan_id.is_manager, 'appraisal_plan_id': item.appraisal_plan_id.id, 'appraisal_type': item.appraisal_type, 'standard_appraisal_employee_line_ids': [Command.create(value) for value in standard_appraisal_list], 'manager_appraisal_line_id': [Command.create(value) for value in manager_appraisal_list], 'employee_protest': item.employee_protest } line_id = self.env['hr.employee.appraisal'].create(appraisal_line) # Initialize total_greed, total_great_level, line_id.level_achieved, line_id.great_level = 0.0, 0.0, 0.0, 0.0 appraisal_result_list = [] if not line_id.is_manager: for line in line_id.standard_appraisal_employee_line_ids: # Update level achieved values when changed in lines total_greed += line.greed total_great_level += line.great_level line_id.great_level = total_great_level line_id.level_achieved = total_greed # Update level achieved percentage when changed in lines if line_id.level_achieved > 0.0 and line_id.great_level > 0.0: line_id.level_achieved_percentage = (line_id.level_achieved * 100) / line_id.great_level # Determine which appraisal result from appraisal percentage appraisal_result = self.env['appraisal.result'].search([ ('result_from', '<', line_id.level_achieved_percentage), ('result_to', '>=', line_id.level_achieved_percentage)]) if len(appraisal_result) > 1: for line in appraisal_result: appraisal_result_list.append(line.name) raise exceptions.UserError( _('Please check appraisal result configuration , there is more than result for ' 'percentage %s are %s ') % ( round(line_id.level_achieved_percentage, 2), appraisal_result_list)) else: line_id.appraisal_result = appraisal_result.id elif line_id.is_manager: for line in line_id.manager_appraisal_line_id: # Update level achieved values when changed in lines total_greed += line.total total_great_level += line.great_level line_id.great_level = total_great_level line_id.level_achieved = total_greed # Update level achieved percentage when changed in lines if line_id.level_achieved > 0.0 and line_id.great_level > 0.0: line_id.level_achieved_percentage = (line_id.level_achieved * 100) / line_id.great_level # Determine which appraisal result from appraisal percentage appraisal_result = self.env['appraisal.result'].search([ ('result_from', '<', line_id.level_achieved_percentage), ('result_to', '>=', line_id.level_achieved_percentage)]) if len(appraisal_result) > 1: for line in appraisal_result: appraisal_result_list.append(line.name) raise exceptions.UserError( _('Please check appraisal result configuration , there is more than result for ' 'percentage %s are %s ') % ( round(line_id.level_achieved_percentage, 2), appraisal_result_list)) else: line_id.appraisal_result = appraisal_result.id appraisal_lines.append(line_id.id) item.appraisal_id = self.env['hr.employee.appraisal'].browse(appraisal_lines) else: raise exceptions.UserError(_('Please select at least one employee to make appraisal.')) item.state = 'gen_appraisal' def start_appraisal(self): self.state = 'start_appraisal' def finish_appraisal(self): # Check if there is appraisal for employee in not in state done if self.appraisal_id: employee_appraisal_list = [] for line in self.appraisal_id: if line.state != 'state_done': employee_appraisal_list.append(line.employee_id.name) if employee_appraisal_list: raise exceptions.UserError( _('Appraisal for employees "%s" is not in state done') % employee_appraisal_list) self.state = 'finish_appraisal' def hr_approval(self): self.state = 'hr_approval' def gm_approval(self): self.state = 'gm_approval' def state_done(self): # make all appraisal for all employees done if self.appraisal_id: for line in self.appraisal_id: line.state = 'closed' self.state = 'done' def draft(self): # Delete all appraisal when re-draft if self.appraisal_id: for line in self.appraisal_id: if line.state == 'draft': line.unlink() self.state = 'draft' elif line.state == 'closed': line.state = 'state_done' self.state = 'start_appraisal' elif line.state == 'state_done': self.state = 'start_appraisal' # Override unlink function def unlink(self): for i in self: if i.state != 'draft': raise exceptions.UserError(_('You can not delete record in state not in draft')) return super(EmployeesAppraisal, self).unlink() # Fill total great level @api.depends('appraisal_id') def fill_totals_great_level(self): for item in self: item.totals_great_level = 0 item.totals_level_achieved = 0 item.totals_level_achieved_percentage = 0 item.totals_appraisal_result = False for element in item.appraisal_id: count_elment = 0 appraisal_result_list = [] # for line in element: count_elment += len(item.appraisal_id) item.totals_great_level += element.great_level / count_elment item.totals_level_achieved += element.level_achieved / count_elment item.totals_level_achieved_percentage = (item.totals_level_achieved / item.totals_great_level) * 100 totals_appraisal_result = self.env['appraisal.result'].search([ ('result_from', '<=', item.totals_level_achieved_percentage), ('result_to', '>=', item.totals_level_achieved_percentage)]) if len(totals_appraisal_result) > 1: for line in totals_appraisal_result: appraisal_result_list.append(line.name) raise exceptions.UserError( _('Please check appraisal result configuration , there is more than result for percentage %s are %s ') % ( round(item.totals_level_achieved_percentage, 2), appraisal_result_list)) else: item.totals_appraisal_result = totals_appraisal_result.id