120 lines
5.2 KiB
Python
120 lines
5.2 KiB
Python
|
# -*- coding: utf-8 -*-
|
||
|
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
||
|
|
||
|
from collections import defaultdict
|
||
|
from datetime import timedelta
|
||
|
|
||
|
from odoo import api, fields, models, _
|
||
|
from odoo.exceptions import ValidationError
|
||
|
from odoo.tools import float_round
|
||
|
|
||
|
|
||
|
class HRLeave(models.Model):
|
||
|
_inherit = 'hr.leave'
|
||
|
|
||
|
overtime_id = fields.Many2one('hr.attendance.overtime', string='Extra Hours')
|
||
|
employee_overtime = fields.Float(related='employee_id.total_overtime')
|
||
|
overtime_deductible = fields.Boolean(compute='_compute_overtime_deductible')
|
||
|
|
||
|
@api.depends('holiday_status_id')
|
||
|
def _compute_overtime_deductible(self):
|
||
|
for leave in self:
|
||
|
leave.overtime_deductible = leave.holiday_status_id.overtime_deductible and leave.holiday_status_id.requires_allocation == 'no'
|
||
|
|
||
|
@api.model_create_multi
|
||
|
def create(self, vals_list):
|
||
|
res = super().create(vals_list)
|
||
|
self._check_overtime_deductible(res)
|
||
|
return res
|
||
|
|
||
|
def write(self, vals):
|
||
|
res = super().write(vals)
|
||
|
fields_to_check = {'number_of_days', 'request_date_from', 'request_date_to', 'state', 'employee_id', 'holiday_status_id'}
|
||
|
if not any(field for field in fields_to_check if field in vals):
|
||
|
return res
|
||
|
if vals.get('holiday_status_id'):
|
||
|
self._check_overtime_deductible(self)
|
||
|
#User may not have access to overtime_id field
|
||
|
for leave in self.sudo().filtered('overtime_id'):
|
||
|
# It must always be possible to refuse leave based on overtime
|
||
|
if vals.get('state') in ['refuse']:
|
||
|
continue
|
||
|
employee = leave.employee_id
|
||
|
duration = leave.number_of_hours_display
|
||
|
overtime_duration = leave.overtime_id.sudo().duration
|
||
|
if overtime_duration != duration:
|
||
|
if duration > employee.total_overtime - overtime_duration:
|
||
|
raise ValidationError(_('The employee does not have enough extra hours to extend this leave.'))
|
||
|
leave.overtime_id.sudo().duration = -1 * duration
|
||
|
return res
|
||
|
|
||
|
def _check_overtime_deductible(self, leaves):
|
||
|
# If the type of leave is overtime deductible, we have to check that the employee has enough extra hours
|
||
|
for leave in leaves:
|
||
|
if not leave.overtime_deductible:
|
||
|
continue
|
||
|
employee = leave.employee_id.sudo()
|
||
|
duration = leave.number_of_hours_display
|
||
|
if duration > employee.total_overtime:
|
||
|
if employee.user_id == self.env.user:
|
||
|
raise ValidationError(_('You do not have enough extra hours to request this leave'))
|
||
|
raise ValidationError(_('The employee does not have enough extra hours to request this leave.'))
|
||
|
if not leave.sudo().overtime_id:
|
||
|
leave.sudo().overtime_id = self.env['hr.attendance.overtime'].sudo().create({
|
||
|
'employee_id': employee.id,
|
||
|
'date': leave.date_from,
|
||
|
'adjustment': True,
|
||
|
'duration': -1 * duration,
|
||
|
})
|
||
|
|
||
|
def action_draft(self):
|
||
|
overtime_leaves = self.filtered('overtime_deductible')
|
||
|
if any([l.employee_overtime < float_round(l.number_of_hours_display, 2) for l in overtime_leaves]):
|
||
|
if self.employee_id.user_id.id == self.env.user.id:
|
||
|
raise ValidationError(_('You do not have enough extra hours to request this leave'))
|
||
|
raise ValidationError(_('The employee does not have enough extra hours to request this leave.'))
|
||
|
|
||
|
res = super().action_draft()
|
||
|
overtime_leaves.overtime_id.sudo().unlink()
|
||
|
for leave in overtime_leaves:
|
||
|
overtime = self.env['hr.attendance.overtime'].sudo().create({
|
||
|
'employee_id': leave.employee_id.id,
|
||
|
'date': leave.date_from,
|
||
|
'adjustment': True,
|
||
|
'duration': -1 * leave.number_of_hours_display
|
||
|
})
|
||
|
leave.sudo().overtime_id = overtime.id
|
||
|
return res
|
||
|
|
||
|
def action_refuse(self):
|
||
|
res = super().action_refuse()
|
||
|
self.sudo().overtime_id.unlink()
|
||
|
return res
|
||
|
|
||
|
def _validate_leave_request(self):
|
||
|
super()._validate_leave_request()
|
||
|
self._update_leaves_overtime()
|
||
|
|
||
|
def _remove_resource_leave(self):
|
||
|
res = super()._remove_resource_leave()
|
||
|
self._update_leaves_overtime()
|
||
|
return res
|
||
|
|
||
|
def _update_leaves_overtime(self):
|
||
|
employee_dates = defaultdict(set)
|
||
|
for leave in self:
|
||
|
if leave.employee_id and leave.employee_company_id.hr_attendance_overtime:
|
||
|
for d in range((leave.date_to - leave.date_from).days + 1):
|
||
|
employee_dates[leave.employee_id].add(self.env['hr.attendance']._get_day_start_and_day(leave.employee_id, leave.date_from + timedelta(days=d)))
|
||
|
if employee_dates:
|
||
|
self.env['hr.attendance'].sudo()._update_overtime(employee_dates)
|
||
|
|
||
|
def unlink(self):
|
||
|
# TODO master change to ondelete
|
||
|
self.sudo().overtime_id.unlink()
|
||
|
return super().unlink()
|
||
|
|
||
|
def _force_cancel(self, *args, **kwargs):
|
||
|
super()._force_cancel(*args, **kwargs)
|
||
|
self.sudo().overtime_id.unlink()
|