419 lines
15 KiB
Python
419 lines
15 KiB
Python
from odoo import models, fields, api
|
|
from odoo.cli.scaffold import template
|
|
|
|
RATING_VALUATION = {
|
|
'1': 'unsatisfactory',
|
|
'2': 'needs_improvements',
|
|
'3': 'meet_expectation',
|
|
'4': 'exceed_expectation',
|
|
'5': 'outstanding',
|
|
}
|
|
|
|
|
|
class EmployeeAppraisalKRA(models.Model):
|
|
_name = 'employee.appraisal.kra'
|
|
_description = 'Key Result Area'
|
|
_order = 'sequence,id'
|
|
|
|
sequence = fields.Integer(string="Sequence", default=10)
|
|
template_appraisal_id = fields.Many2one('employee.appraisal.template', string="Template", ondelete='cascade')
|
|
name = fields.Text(string="KRA Name", required=True)
|
|
description = fields.Text(string="KRA Description", required=True)
|
|
kra_weightage = fields.Float(string="KRA Weightage", compute='_compute_kpi_weightage', store=True)
|
|
max_star_rating = fields.Selection([
|
|
('0', '0'),
|
|
('1', '1'),
|
|
('2', '2'),
|
|
('3', '3'),
|
|
('4', '4'),
|
|
('5', '5'),
|
|
], string='Maximum Stars', default='5')
|
|
max_points = fields.Float(string='Maximum Points', default=10)
|
|
kpi_line_ids = fields.One2many('employee.appraisal.kpi', 'kra_id', string="KPI Questions", copy=True)
|
|
kpi_count = fields.Integer(compute="_compute_kpi_count")
|
|
kra_template_rating_bool = fields.Boolean(related='template_appraisal_id.template_rating_bool', readonly=True)
|
|
kra_template_point_bool = fields.Boolean(related='template_appraisal_id.template_point_bool', readonly=True)
|
|
|
|
def _compute_kpi_count(self):
|
|
for rec in self:
|
|
rec.kpi_count = len(rec.kpi_line_ids)
|
|
|
|
@api.onchange('kpi_line_ids')
|
|
def _onchange_kpi_line_ids(self):
|
|
for rec in self:
|
|
if (
|
|
rec.template_appraisal_id
|
|
and rec.template_appraisal_id.template_point_bool
|
|
):
|
|
count = len(rec.kpi_line_ids)
|
|
|
|
if count:
|
|
point_per_kpi = rec.max_points / count
|
|
|
|
for kpi in rec.kpi_line_ids:
|
|
kpi.kpi_points = point_per_kpi
|
|
|
|
@api.onchange('template_appraisal_id')
|
|
def onchange_template_appraisal_id(self):
|
|
for rec in self:
|
|
template = rec.template_appraisal_id
|
|
if template.template_rating_bool:
|
|
rec.max_star_rating = '5'
|
|
if template.template_point_bool:
|
|
rec.max_points = 10
|
|
|
|
@api.depends('kpi_line_ids.kpi_weightage')
|
|
def _compute_kpi_weightage(self):
|
|
for rec in self:
|
|
rec.kra_weightage = sum(rec.kpi_line_ids.mapped('kpi_weightage'))
|
|
|
|
def action_open_questions(self):
|
|
return {
|
|
'type': 'ir.actions.act_window',
|
|
'name': 'KPI Questions',
|
|
'res_model': 'employee.appraisal.kpi',
|
|
'view_mode': 'list,form',
|
|
'domain': [('kra_id', '=', self.id)],
|
|
'context': {
|
|
'default_kra_id': self.id
|
|
},
|
|
'target': 'new',
|
|
}
|
|
|
|
|
|
class EmployeeAppraisalKPI(models.Model):
|
|
_name = 'employee.appraisal.kpi'
|
|
_description = 'Key Performance Indicator'
|
|
_order = 'sequence,id'
|
|
|
|
sequence = fields.Integer(string="Sequence", default=10)
|
|
kra_id = fields.Many2one('employee.appraisal.kra', string="KRA", ondelete='cascade')
|
|
name = fields.Text(string="KPI / Question", required=True)
|
|
kpi_description = fields.Text('Description')
|
|
kpi_weightage = fields.Float(string="KRI Weightage")
|
|
kpi_ratings = fields.Integer(string="KRI Ratings", default=5)
|
|
kpi_points = fields.Integer(string="KRI Points")
|
|
|
|
def action_delete_record(self):
|
|
kra_id = self.kra_id.id
|
|
self.unlink()
|
|
return {
|
|
'type': 'ir.actions.act_window',
|
|
'name': 'KPI Questions',
|
|
'res_model': 'employee.appraisal.kpi',
|
|
'view_mode': 'list,form',
|
|
'domain': [('kra_id', '=', kra_id)],
|
|
'context': {
|
|
'default_kra_id': kra_id
|
|
},
|
|
'target': 'new',
|
|
}
|
|
|
|
|
|
class EmployeeAppraisalKRALine(models.Model):
|
|
_name = 'employee.appraisal.kra.line'
|
|
|
|
config_id = fields.Many2one(
|
|
'employee.appraisal.template.config',
|
|
ondelete='cascade'
|
|
)
|
|
template_empl_rating_bool = fields.Boolean(
|
|
related='config_id.template_empl_rating_bool',
|
|
readonly=True
|
|
)
|
|
template_empl_point_bool = fields.Boolean(related='config_id.template_empl_point_bool', readonly=True)
|
|
kra_id = fields.Many2one('employee.appraisal.kra')
|
|
name = fields.Text('KRA Name')
|
|
sequence = fields.Integer(default=10)
|
|
description_line_kra = fields.Text('Description')
|
|
kra_line_weightage = fields.Float(string="KRA Point Weightage", compute="_compute_kra_line_weightage", store=True)
|
|
kra_line_star_weightage = fields.Integer(string="KRA Star Weightage", compute="_compute_kra_line_star_weightage",
|
|
store=True)
|
|
kra_line_star_demo_weightage = fields.Selection([
|
|
('0', '0'),
|
|
('1', '1'),
|
|
('2', '2'),
|
|
('3', '3'),
|
|
('4', '4'),
|
|
('5', '5'),
|
|
], compute='_compute_kra_line_demo_star_weightage', store=True)
|
|
kpi_line_ids = fields.One2many('employee.appraisal.kpi.line', 'kra_line_id', string="Questions")
|
|
kpi_count_line = fields.Integer(compute="_compute_kpi_count_line")
|
|
max_kra_points = fields.Float(string='Maximum KRA Points')
|
|
max_kra_stars = fields.Integer(string='Maximum KRA Stars')
|
|
employee_kra_points = fields.Float(compute='_compute_employee_kra_points', store=True)
|
|
employee_kra_stars = fields.Float(compute='_compute_employee_kra_stars', store=True)
|
|
manager_kra_points = fields.Float(compute='_compute_kra_scores', store=True)
|
|
hr_kra_points = fields.Float(compute='_compute_kra_scores', store=True)
|
|
manager_kra_stars = fields.Float(compute='_compute_kra_scores', store=True)
|
|
hr_kra_stars = fields.Float(compute='_compute_kra_scores', store=True)
|
|
kra_line_star_display = fields.Char(compute='_compute_kra_line_star_display', string='Rating')
|
|
kra_line_rating = fields.Char(compute="_compute_kra_line_star_display",string="Rating")
|
|
|
|
@api.depends('kpi_line_ids.rating_star','kpi_line_ids.manager_rating_star','kpi_line_ids.hr_rating_star')
|
|
def _compute_kra_line_star_display(self):
|
|
for rec in self:
|
|
ratings = []
|
|
ratings += [
|
|
int(kpi.rating_star)
|
|
for kpi in rec.kpi_line_ids
|
|
if kpi.rating_star
|
|
]
|
|
ratings += [
|
|
int(kpi.manager_rating_star)
|
|
for kpi in rec.kpi_line_ids
|
|
if kpi.manager_rating_star
|
|
]
|
|
ratings += [
|
|
int(kpi.hr_rating_star)
|
|
for kpi in rec.kpi_line_ids
|
|
if kpi.hr_rating_star
|
|
]
|
|
if ratings:
|
|
avg = round(sum(ratings) / len(ratings))
|
|
rec.kra_line_star_display = "★" * avg + "☆" * (5 - avg)
|
|
rec.kra_line_rating = f"({avg})"
|
|
else:
|
|
rec.kra_line_star_display = "☆☆☆☆☆"
|
|
rec.kra_line_rating = "(0)"
|
|
|
|
@api.depends('kpi_line_ids.employee_score','kpi_line_ids.manager_score','kpi_line_ids.hr_score')
|
|
def _compute_kra_line_weightage(self):
|
|
for rec in self:
|
|
employee_total = sum(
|
|
rec.kpi_line_ids.mapped('employee_score')
|
|
)
|
|
|
|
manager_total = sum(
|
|
rec.kpi_line_ids.mapped('manager_score')
|
|
)
|
|
|
|
hr_total = sum(
|
|
rec.kpi_line_ids.mapped('hr_score')
|
|
)
|
|
|
|
rec.kra_line_weightage = (
|
|
employee_total +
|
|
manager_total +
|
|
hr_total
|
|
) / 3
|
|
|
|
@api.depends('kpi_line_ids.rating_star')
|
|
def _compute_kra_line_star_weightage(self):
|
|
for rec in self:
|
|
ratings = [
|
|
int(kpi.rating_star)
|
|
for kpi in rec.kpi_line_ids
|
|
if kpi.rating_star
|
|
]
|
|
|
|
rec.kra_line_star_weightage = (
|
|
sum(ratings) / len(ratings)
|
|
if ratings else 0
|
|
)
|
|
|
|
@api.depends(
|
|
'kpi_line_ids.employee_score',
|
|
'kpi_line_ids.manager_score',
|
|
'kpi_line_ids.hr_score',
|
|
'kpi_line_ids.rating_star',
|
|
'kpi_line_ids.manager_rating_star',
|
|
'kpi_line_ids.hr_rating_star'
|
|
)
|
|
def _compute_kra_scores(self):
|
|
for rec in self:
|
|
# --------------------------
|
|
# POINTS
|
|
# --------------------------
|
|
|
|
rec.employee_kra_points = sum(
|
|
rec.kpi_line_ids.mapped('employee_score')
|
|
)
|
|
|
|
rec.manager_kra_points = sum(
|
|
rec.kpi_line_ids.mapped('manager_score')
|
|
)
|
|
|
|
rec.hr_kra_points = sum(
|
|
rec.kpi_line_ids.mapped('hr_score')
|
|
)
|
|
|
|
# --------------------------
|
|
# STARS
|
|
# --------------------------
|
|
|
|
emp_stars = [
|
|
int(x.rating_star)
|
|
for x in rec.kpi_line_ids
|
|
if x.rating_star
|
|
]
|
|
|
|
mgr_stars = [
|
|
int(x.manager_rating_star)
|
|
for x in rec.kpi_line_ids
|
|
if x.manager_rating_star
|
|
]
|
|
|
|
hr_stars = [
|
|
int(x.hr_rating_star)
|
|
for x in rec.kpi_line_ids
|
|
if x.hr_rating_star
|
|
]
|
|
|
|
rec.employee_kra_stars = (
|
|
round(sum(emp_stars) / len(emp_stars), 2)
|
|
if emp_stars else 0
|
|
)
|
|
|
|
rec.manager_kra_stars = (
|
|
round(sum(mgr_stars) / len(mgr_stars), 2)
|
|
if mgr_stars else 0
|
|
)
|
|
|
|
rec.hr_kra_stars = (
|
|
round(sum(hr_stars) / len(hr_stars), 2)
|
|
if hr_stars else 0
|
|
)
|
|
|
|
@api.depends('kpi_line_ids.rating_star')
|
|
def _compute_kra_line_demo_star_weightage(self):
|
|
for rec in self:
|
|
ratings = [
|
|
int(kpi.rating_star)
|
|
for kpi in rec.kpi_line_ids
|
|
if kpi.rating_star
|
|
]
|
|
|
|
if ratings:
|
|
avg = round(sum(ratings) / len(ratings))
|
|
rec.kra_line_star_demo_weightage = str(avg)
|
|
else:
|
|
rec.kra_line_star_demo_weightage = '0'
|
|
|
|
def _compute_kpi_count_line(self):
|
|
for rec in self:
|
|
rec.kpi_count_line = len(rec.kpi_line_ids)
|
|
|
|
def action_open_questions_line(self):
|
|
self.ensure_one()
|
|
|
|
return {
|
|
'type': 'ir.actions.act_window',
|
|
'name': 'KRA Evaluation',
|
|
'res_model': 'employee.appraisal.kra.line',
|
|
'res_id': self.id,
|
|
'view_mode': 'form',
|
|
'target': 'new',
|
|
}
|
|
|
|
|
|
class EmployeeAppraisalKPILine(models.Model):
|
|
_name = 'employee.appraisal.kpi.line'
|
|
_rec_name = 'question'
|
|
|
|
sequence = fields.Integer(default=10)
|
|
kra_line_id = fields.Many2one('employee.appraisal.kra.line', ondelete='cascade')
|
|
kra_name = fields.Text()
|
|
question = fields.Text(string="KPI")
|
|
kpi_line_weightage = fields.Float(string="Given KPI Weightage")
|
|
description = fields.Text()
|
|
employee_score = fields.Float()
|
|
manager_score = fields.Float()
|
|
hr_score = fields.Float()
|
|
template_empl_rating_bool = fields.Boolean(related='kra_line_id.config_id.template_empl_rating_bool', readonly=True)
|
|
template_empl_point_bool = fields.Boolean(related='kra_line_id.config_id.template_empl_point_bool', readonly=True)
|
|
manager_kpi_points = fields.Float(string="Maximum KPI Points")
|
|
manager_kpi_stars = fields.Integer(string="Maximum KPI Stars")
|
|
rating = fields.Selection([
|
|
('1', '1'),
|
|
('2', '2'),
|
|
('3', '3'),
|
|
('4', '4'),
|
|
('5', '5'),
|
|
], string="Rating")
|
|
rating_value = fields.Selection([
|
|
('unsatisfactory', 'Unsatisfactory'),
|
|
('needs_improvements', 'Needs Improvements'),
|
|
('meet_expectation', 'Meets Expectation'),
|
|
('exceed_expectation', 'Exceeds Expectation'),
|
|
('outstanding', 'Outstanding'),
|
|
], string="Rating Value")
|
|
rating_star = fields.Selection([
|
|
('0', '0'),
|
|
('1', '1'),
|
|
('2', '2'),
|
|
('3', '3'),
|
|
('4', '4'),
|
|
('5', '5'),
|
|
], string="Stars", copy=False)
|
|
manager_rating_star = fields.Selection([
|
|
('0', '0'),
|
|
('1', '1'),
|
|
('2', '2'),
|
|
('3', '3'),
|
|
('4', '4'),
|
|
('5', '5'),
|
|
], string="Stars", copy=False)
|
|
hr_rating_star = fields.Selection([
|
|
('0', '0'),
|
|
('1', '1'),
|
|
('2', '2'),
|
|
('3', '3'),
|
|
('4', '4'),
|
|
('5', '5'),
|
|
], string="Stars", copy=False)
|
|
is_employee_reviewer = fields.Boolean(compute="_compute_user_roles", store=False)
|
|
is_manager_reviewer = fields.Boolean(compute="_compute_user_roles", store=False)
|
|
is_hr_reviewer = fields.Boolean(compute="_compute_user_roles", store=False)
|
|
|
|
def _compute_user_roles(self):
|
|
current_user = self.env.user
|
|
for rec in self:
|
|
rec.is_employee_reviewer = (
|
|
rec.kra_line_id.config_id.employee_appraisal_id.user_id.id == current_user.id)
|
|
rec.is_manager_reviewer= (
|
|
rec.kra_line_id.config_id.managerapp_id.user_id.id == current_user.id)
|
|
rec.is_hr_reviewer= (
|
|
rec.kra_line_id.config_id.hr_apprai_id.user_id.id == current_user.id
|
|
)
|
|
|
|
# self_rating = fields.Selection([
|
|
# ('0', '0'),
|
|
# ('1', '1'),
|
|
# ('2', '2'),
|
|
# ('3', '3'),
|
|
# ('4', '4'),
|
|
# ('5', '5'),
|
|
# ], string='Self Rating', compute="_compute_self_rating")
|
|
#
|
|
# @api.depends('program_id.self_other_ev_line_ids.rating_star')
|
|
# def _compute_self_rating(self):
|
|
# for line in self:
|
|
# other_line = line.program_id.self_other_ev_line_ids.filtered(lambda l: l.name == line.name)
|
|
# line.self_rating = other_line.rating_star if other_line else False
|
|
|
|
@api.onchange('rating')
|
|
def _onchange_rating(self):
|
|
for rec in self:
|
|
if rec.rating:
|
|
rec.rating_value = RATING_VALUATION.get(rec.rating)
|
|
rec.rating_star = rec.rating
|
|
else:
|
|
rec.rating_value = 0
|
|
rec.rating_star = 0
|
|
|
|
@api.onchange('rating_star')
|
|
def _onchange_rating_star(self):
|
|
for rec in self:
|
|
rec.rating_value = RATING_VALUATION.get(
|
|
rec.rating_star,
|
|
False
|
|
)
|
|
|
|
|
|
class ResCompany(models.Model):
|
|
_inherit = 'res.company'
|
|
|
|
short_code = fields.Char(string="Short Code")
|
|
company_registry_placeholder = fields.Char(string="Short Code")
|