from odoo import api, fields, models,_ from odoo.exceptions import ValidationError from dateutil.relativedelta import relativedelta class AppraisalYear(models.Model): _name = 'employee.appraisal.year' _description = 'Employee Appraisal Year' _order = "year_seq" _rec_name = 'appraisal_name' year = fields.Integer(string="Performance Period") appraisal_name_id = fields.Char(string="Appraisal Type") appraisal_name = fields.Char(string="Appraisal Name") start_month = fields.Date('Starting Month') end_month = fields.Date('End Month') active = fields.Boolean(default=True) year_seq = fields.Integer(string="Sequence") appraisal_type_id = fields.Many2one( 'employee.appraisal.type', string="Appraisal Type" ) @api.constrains('appraisal_type_id', 'start_month', 'end_month') def _check_appraisal_type(self): for rec in self: if not rec.start_month or not rec.end_month: continue if rec.start_month > rec.end_month: raise ValidationError( _("Start Month cannot be greater than End Month.") ) expected_end = False if rec.appraisal_type_id.name == 'Monthly': expected_end = rec.start_month + relativedelta(months=1, days=-1) elif rec.appraisal_type_id.name == 'Quarterly': expected_end = rec.start_month + relativedelta(months=3, days=-1) elif rec.appraisal_type_id.name == 'Half-yearly': expected_end = rec.start_month + relativedelta(months=6, days=-1) elif rec.appraisal_type_id.name == 'Annual': expected_end = rec.start_month + relativedelta(months=12, days=-1) if expected_end and rec.end_month != expected_end: raise ValidationError(_( "Invalid period for %s.\nExpected End Date: %s" ) % ( rec.appraisal_type_id.name, expected_end.strftime('%d/%m/%Y') )) duplicate = self.search([ ('id', '!=', rec.id), ('appraisal_type_id', '=', rec.appraisal_type_id.id), ('start_month', '<=', rec.end_month), ('end_month', '>=', rec.start_month), ], limit=1) if duplicate: raise ValidationError( _("This appraisal period overlaps with existing period: %s") % duplicate.appraisal_name ) class EmployeeAppraisalType(models.Model): _name = 'employee.appraisal.type' _description = 'Employee Appraisal Type' name = fields.Char(required=True) seq = fields.Integer(string="Sequence") class AppraisalTemplate(models.Model): _name = 'employee.appraisal.template' _inherit = ['mail.thread', 'mail.activity.mixin'] _description = 'Employee Appraisal Template' _order = "seq desc" _rec_name = 'seq' name = fields.Char(string="Name") employee_evaluator_name_id = fields.Many2one('employee.appraisal.evaluator', string="Employee Appraisal Evaluator") employee_eva_id = fields.Many2one('hr.employee',string="Manager") hr_head_employee_id = fields.Many2one('hr.employee',string="Head HR") image_template = fields.Image(related='employee_eva_id.image_1920', string="Image") hr_employee_id = fields.Many2one('hr.employee',string="Employee HR Employee") employee_department_id = fields.Many2one('hr.department',string="Department") company_id = fields.Many2one('res.company', string="Company",default=lambda self: self.env.company) email_notify_user_ids = fields.Many2many("res.users", string='Notify Users if New Evaluation Submited and Confirmed') hr_email_notify = fields.Boolean("Send Email if HR APPROVE or REJECT Evaluation") template_rating_bool = fields.Boolean() template_point_bool = fields.Boolean() stage_config_ids = fields.Many2many('employee.stage.config',string='Stages') employee_state = fields.Selection([ ('new', 'New'), ('sent', 'sent'), ], string='Status', copy=False, tracking=1, default='new') kra_ids = fields.One2many('employee.appraisal.kra','template_appraisal_id',string="Key Result Areas",copy=True,tracking=True) kra_weightage = fields.Integer(compute="_compute_total_kra_weightage",string="Total KRA Weightage") notice_id = fields.Many2one('hr.notice.appraisal',string="Notice") start_date = fields.Date(string="Start Date") end_date = fields.Date(string="End Date") is_readonly = fields.Boolean(compute="_compute_is_readonly") mail_sent_employee_ids = fields.Many2many('hr.employee',string="Mail Sent Employees") seq = fields.Char(string="Sequence",readonly=True,copy=False) employee_ids = fields.Many2many('hr.employee','appraisal_employee_rel','appraisal_id','employee_id',string="Employees") manager_ids = fields.Many2many('hr.employee','appraisal_manager_rel','appraisal_id','manager_id',string="Managers") appraisal_period_id = fields.Many2one('employee.appraisal.year') appraisal_period_type_id = fields.Many2one('employee.appraisal.type') @api.depends('kra_ids.kra_weightage') def _compute_total_kra_weightage(self): for rec in self: rec.kra_weightage = sum( rec.kra_ids.mapped('kra_weightage')) def action_sent_employee(self): for rec in self: if not rec.kra_ids.name: raise ValidationError('Please create KRA') if not rec.kra_ids.mapped('kpi_line_ids'): raise ValidationError('Please create KPI') # appraisal_config_obj = self.env['employee.appraisal.template.config'] # for rec in self: # first_stage = rec.stage_config_ids.sorted( # key=lambda s: s.seq # )[:1] # for employee in rec.employee_ids: # already_exists = appraisal_config_obj.search([ # ('template_id', '=', rec.id), # ('employee_appraisal_id', '=', employee.id) # ], limit=1) # if already_exists: # continue # appraisal = appraisal_config_obj.create({ # 'template_id': rec.id, # 'seq': rec.seq, # 'employee_appraisal_id': employee.id, # 'employee_ids': [(6, 0, rec.employee_ids.ids)], # 'manager_ids': [(6, 0, rec.manager_ids.ids)], # 'notice_id': rec.notice_id.id, # 'start_date': rec.start_date, # 'end_date': rec.end_date, # 'appraisal_period_id': rec.appraisal_period_id.id, # 'hr_apprai_id': rec.hr_employee_id.id, # 'managerapp_id': rec.employee_eva_id.id, # 'template_empl_rating_bool': rec.template_rating_bool, # 'template_empl_point_bool': rec.template_point_bool, # 'available_stage_ids': [ # (6, 0, rec.stage_config_ids.ids) # ], # 'stage_id': first_stage.id if first_stage else False, # # 'state': 'self_evaluation', # }) # appraisal._onchange_template_id() employee_emails = rec.employee_ids.mapped('work_email') manager_emails = rec.manager_ids.mapped('work_email') all_emails = employee_emails + manager_emails partner_ids = ( self.employee_ids.mapped('user_id.partner_id')) email_to = ",".join(filter(None, all_emails)) body_html = f"""
Hello Team,
Employee appraisal process has been initiated.
| Reference | {rec.seq or ''} |
| Appraisal Template | {rec.name or ''} |
| Start Date | {rec.start_date or ''} |
| End Date | {rec.end_date or ''} |
Please complete the appraisal within timeline.
Regards,
Team Manager