odoo18/addons_extensions/hrms_employee_appraisal/models/kpi_kra.py

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")