odex30_standard/exp_payroll_promotion/models/hr_payroll_raise.py

219 lines
11 KiB
Python

# -*- coding: utf-8 -*-
from dateutil.relativedelta import relativedelta
from odoo import models, fields, api, _
from odoo.exceptions import ValidationError
class HrPayrollRaise(models.Model):
_name = 'hr.payroll.raise'
_inherit = ['mail.thread', 'mail.activity.mixin']
_description = "Employee annual raises"
_order = "employee_id asc, id desc"
employee_id = fields.Many2one('hr.employee', 'Employee', required=True, domain=[('state', '=', 'open')])
application_date = fields.Date('Application Date', required=True)
raise_type = fields.Selection(selection=[('annual', 'Annual'), ('discrimination', 'Discrimination'),
('exceptional', 'Exceptional')
], string='Raise Type', required=True, default='exceptional')
margin = fields.Float('Time Margin')
deviation = fields.Float('Deviation in Days', compute='_compute_deviation', store=True, default=0)
scale_id = fields.Many2one('hr.payroll.structure', 'Scale', domain=[('type', '=', 'scale')])
level_id = fields.Many2one('hr.payroll.structure', 'Level', domain=[('type', '=', 'level')])
group_id = fields.Many2one('hr.payroll.structure', 'Group', domain=[('type', '=', 'group')])
degree_id = fields.Many2one('hr.payroll.structure', 'Degrees', domain=[('type', '=', 'degree')])
nominated_degree_id = fields.Many2one('hr.payroll.structure', 'Nominated Degree',
domain=[('type', '=', 'degree')])
last_raise_date = fields.Date('Last Raise Date')
next_raise_date = fields.Date('Next Raise Date')
note = fields.Html('Notes')
state = fields.Selection([('draft', 'Draft'),
('hr_officer', 'HR Officer'),
('confirm', 'HR Manager'),
('approve', 'Approved'),
('refuse', 'Refused')], 'State', default='draft', tracking=True)
last_raises = fields.Boolean(string='Last Raise', default=True, readonly=True)
current_salary = fields.Float(string='Current Salary', store=True)
current_salary_insurance = fields.Float(string='Salary Insurance', store=True)
percentage_bonus = fields.Boolean(string='Percentage Bonus')
percentage_raises = fields.Float(string='Percentage Raises')
new_salary = fields.Float(string='New Basic Salary', store=True)
re_contract_id = fields.Many2one('hr.re.contract', 'Re-Contract', readonly=True)
employee_appraisal = fields.Many2one('hr.employee.appraisal', string="Employee Appraisal", readonly=True, store=True)
is_required = fields.Boolean(string='Is Required', compute='_compute_is_required')
@api.depends('employee_id', 'employee_id.employee_type_id', 'employee_id.employee_type_id.salary_type')
def _compute_is_required(self):
for rec in self:
rec.is_required = True
if rec.employee_id and rec.employee_id.employee_type_id and rec.employee_id.employee_type_id.salary_type == 'amount':
rec.is_required = False
@api.onchange('employee_id', 'percentage_bonus', 'percentage_raises')
def onchange_employee(self):
self.nominated_degree_id = False
if self.employee_id:
self.employee_appraisal = self.employee_id.contract_id.appraisal_result.id
self.scale_id = self.employee_id.salary_scale.id
self.level_id = self.employee_id.salary_level.id
self.group_id = self.employee_id.salary_group.id
self.degree_id = self.employee_id.salary_degree.id
self.last_raise_date = self.employee_id.degree_date
self.current_salary = self.employee_id.contract_id.salary
self.current_salary_insurance = self.employee_id.contract_id.salary_insurnce
rs_dt = self.employee_id.degree_date and self.employee_id.degree_date or self.employee_id.first_hiring_date
if rs_dt and self.employee_id.degree_date:
ndate = fields.Date.from_string(rs_dt) + relativedelta(days=self.employee_id.salary_degree.time_margin
) or False
self.next_raise_date = ndate
if self.percentage_bonus == True:
self.new_salary = round((self.current_salary * self.percentage_raises) / 100 + self.current_salary, 2)
if self.employee_appraisal:
self.percentage_raises = self.employee_appraisal.level_achieved_percentage * self.scale_id.Percentage_increase
@api.onchange('nominated_degree_id')
def onchange_degree(self):
self.new_salary = self.nominated_degree_id.base_salary
if self.employee_id and self.nominated_degree_id and self.degree_id and \
self.nominated_degree_id.sequence < self.degree_id.sequence:
raise ValidationError(_('Sorry nominated degree %s is less than the current employee degree')
% self.nominated_degree_id.name)
@api.depends('nominated_degree_id', 'application_date')
def _compute_deviation(self):
for rec in self:
if not rec.application_date:
rec.deviation = 0
continue
if rec.nominated_degree_id and rec.degree_id:
days_to_raise = 0
degress_between = self.env['hr.payroll.structure'].search(
[('salary_scale_level_id', '=', rec.level_id.id),
('salary_scale_group_id', '=', rec.group_id.id),
('salary_scale_id', '=', rec.scale_id.id),
('sequence', '>=', rec.degree_id.sequence),
('sequence', '<', rec.nominated_degree_id.sequence)])
for dg in degress_between:
days_to_raise += dg.time_margin
degree_date = rec.employee_id.degree_date and rec.employee_id.degree_date or \
rec.employee_id.first_hiring_date
if not degree_date:
rec.deviation = 0
continue
passed_days = rec.employee_id and \
(fields.Date.from_string(rec.application_date) - fields.Date.from_string(
degree_date)).days or 0
rec.deviation = passed_days - days_to_raise
rs_dt = rec.employee_id.degree_date and rec.employee_id.degree_date or rec.employee_id.first_hiring_date
if rs_dt and rec.employee_id.salary_degree:
ndate = fields.Date.from_string(rs_dt) + relativedelta(
days=rec.employee_id.salary_degree.time_margin) or False
rec.next_raise_date = ndate
else:
rec.deviation = 0
def hr_officer(self):
if self.percentage_bonus == True and self.percentage_raises <= 0:
raise ValidationError(_('Sorry, The Percentage Of Bonus Increase Must Be Greater Than Zero'))
self.state = 'hr_officer'
def act_confirm(self):
self.state = 'confirm'
def act_approve(self):
for rec in self:
if not rec.percentage_bonus:
rec.employee_id.degree_date = rec.application_date
rec.employee_id.contract_id.salary_degree = rec.nominated_degree_id.id
rec.employee_id.contract_id.salary = rec.nominated_degree_id.base_salary
rec.employee_id.contract_id.salary_insurnce = rec.nominated_degree_id.base_salary
last_raise = self.search([('employee_id', '=', rec.employee_id.id),
('id', '!=', rec.id),
('level_id', '=', rec.level_id.id),
('group_id', '=', rec.group_id.id),
('scale_id', '=', rec.scale_id.id),
('state', '=', 'approve')], order='application_date desc', limit=1)
if last_raise:
last_raise.last_raises = False
else:
if rec.percentage_bonus == True and rec.percentage_raises > 0:
rec.employee_id.contract_id.salary = rec.new_salary
rec.employee_id.contract_id.salary_insurnce = rec.employee_id.contract_id.salary
rec.state = 'approve'
def act_refuse(self):
self.state = 'refuse'
def act_reset(self):
for rec in self:
if not rec.last_raises:
raise ValidationError(_('Sorry you can not set to Draft this Not last Raise'))
rec.employee_id.contract_id.salary_degree = rec.degree_id.id
last_raise = rec.search([('employee_id', '=', rec.employee_id.id),
('id', '!=', rec.id),
('level_id', '=', rec.level_id.id),
('group_id', '=', rec.group_id.id),
('scale_id', '=', rec.scale_id.id),
('state', '=', 'approve')], order='application_date desc', limit=1)
rec.employee_id.degree_date = last_raise and last_raise.application_date or \
rec.employee_id.first_hiring_date
rec.employee_id.contract_id.salary = rec.current_salary
rec.employee_id.contract_id.salary_insurnce = rec.current_salary_insurance
if last_raise:
last_raise.last_raises = True
rec.state = 'draft'
def unlink(self):
for rec in self:
if rec.state != 'draft':
raise ValidationError(_('Sorry you can not delete a record that is not in draft state'))
return super(HrPayrollRaise, self).unlink()
def write(self, vals):
res = super(HrPayrollRaise, self).write(vals)
if 'state' in vals:
for rec in self:
if rec.nomination_id:
rec.nomination_id.check_raise_nominee()
return res
class hr_extend(models.Model):
_inherit = 'hr.re.contract'
raise_ids = fields.One2many('hr.payroll.raise', 're_contract_id', string="Employee Raise")
@api.onchange('employee_id')
def onchange_emp(self):
for rec in self:
if rec.raise_ids:
for line in rec.raise_ids:
if line.state != 'draft':
raise ValidationError(_('You can not Change Employee Name Has Annual raise in state not in Draft'))
else:
rec.raise_ids = False
def unlink(self):
for i in self:
if i.state != 'draft':
raise ValidationError(_('You can not delete record in state not in draft'))
if i.raise_ids:
for rec in i.raise_ids:
if rec.state != 'draft':
raise ValidationError(_('You can not delete record Has Employee Annual raise in state not in Draft'))
rec.unlink()
return super(hr_extend, i).unlink()