Files
odoo_source/addons/hr_holidays/models/hr.py
T
Yannick TivisseandCas Vissers 02ce0022b2 [FIX] hr_holidays: Fix remaining leaves count on employee form
Purpose
=======

Currently the remaining leaves substract the taken leaves with
no needed allocation.

That way, sick leaves are removed from the remaining leaves for example.

Closes #28659

Co-authored-by: Cas Vissers <c.vissers@brahoo.nl>

closes odoo/odoo#28951
2018-11-22 11:35:08 +00:00

205 lines
9.8 KiB
Python

# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
import datetime
from dateutil.relativedelta import relativedelta
from odoo import api, fields, models, _
from odoo.exceptions import UserError
from odoo.tools.float_utils import float_round
class Department(models.Model):
_inherit = 'hr.department'
absence_of_today = fields.Integer(
compute='_compute_leave_count', string='Absence by Today')
leave_to_approve_count = fields.Integer(
compute='_compute_leave_count', string='Leave to Approve')
allocation_to_approve_count = fields.Integer(
compute='_compute_leave_count', string='Allocation to Approve')
total_employee = fields.Integer(
compute='_compute_total_employee', string='Total Employee')
@api.multi
def _compute_leave_count(self):
Requests = self.env['hr.leave']
Allocations = self.env['hr.leave.allocation']
today_date = datetime.datetime.utcnow().date()
today_start = fields.Datetime.to_string(today_date) # get the midnight of the current utc day
today_end = fields.Datetime.to_string(today_date + relativedelta(hours=23, minutes=59, seconds=59))
leave_data = Requests.read_group(
[('department_id', 'in', self.ids),
('state', '=', 'confirm')],
['department_id'], ['department_id'])
allocation_data = Allocations.read_group(
[('department_id', 'in', self.ids),
('state', '=', 'confirm')],
['department_id'], ['department_id'])
absence_data = Requests.read_group(
[('department_id', 'in', self.ids), ('state', 'not in', ['cancel', 'refuse']),
('date_from', '<=', today_end), ('date_to', '>=', today_start)],
['department_id'], ['department_id'])
res_leave = dict((data['department_id'][0], data['department_id_count']) for data in leave_data)
res_allocation = dict((data['department_id'][0], data['department_id_count']) for data in allocation_data)
res_absence = dict((data['department_id'][0], data['department_id_count']) for data in absence_data)
for department in self:
department.leave_to_approve_count = res_leave.get(department.id, 0)
department.allocation_to_approve_count = res_allocation.get(department.id, 0)
department.absence_of_today = res_absence.get(department.id, 0)
@api.multi
def _compute_total_employee(self):
emp_data = self.env['hr.employee'].read_group([('department_id', 'in', self.ids)], ['department_id'], ['department_id'])
result = dict((data['department_id'][0], data['department_id_count']) for data in emp_data)
for department in self:
department.total_employee = result.get(department.id, 0)
class Employee(models.Model):
_inherit = "hr.employee"
remaining_leaves = fields.Float(
compute='_compute_remaining_leaves', string='Remaining Legal Leaves',
help='Total number of legal leaves allocated to this employee, change this value to create allocation/leave request. '
'Total based on all the leave types without overriding limit.')
current_leave_state = fields.Selection(compute='_compute_leave_status', string="Current Leave Status",
selection=[
('draft', 'New'),
('confirm', 'Waiting Approval'),
('refuse', 'Refused'),
('validate1', 'Waiting Second Approval'),
('validate', 'Approved'),
('cancel', 'Cancelled')
])
current_leave_id = fields.Many2one('hr.leave.type', compute='_compute_leave_status', string="Current Leave Type")
leave_date_from = fields.Date('From Date', compute='_compute_leave_status')
leave_date_to = fields.Date('To Date', compute='_compute_leave_status')
leaves_count = fields.Float('Number of Leaves', compute='_compute_leaves_count')
show_leaves = fields.Boolean('Able to see Remaining Leaves', compute='_compute_show_leaves')
is_absent_totay = fields.Boolean('Absent Today', compute='_compute_absent_employee', search='_search_absent_employee')
def _get_remaining_leaves(self):
""" Helper to compute the remaining leaves for the current employees
:returns dict where the key is the employee id, and the value is the remain leaves
"""
self._cr.execute("""
SELECT
sum(h.number_of_days) AS days,
h.employee_id
FROM
(
SELECT holiday_status_id, number_of_days,
state, employee_id
FROM hr_leave_allocation
UNION
SELECT holiday_status_id, (number_of_days * -1) as number_of_days,
state, employee_id
FROM hr_leave
) h
join hr_leave_type s ON (s.id=h.holiday_status_id)
WHERE
h.state='validate' AND
(s.allocation_type='fixed' OR s.allocation_type='fixed_allocation') AND
h.employee_id in %s
GROUP BY h.employee_id""", (tuple(self.ids),))
return dict((row['employee_id'], row['days']) for row in self._cr.dictfetchall())
@api.multi
def _compute_remaining_leaves(self):
remaining = self._get_remaining_leaves()
for employee in self:
employee.remaining_leaves = float_round(remaining.get(employee.id, 0.0), precision_digits=2)
@api.multi
def _compute_leave_status(self):
# Used SUPERUSER_ID to forcefully get status of other user's leave, to bypass record rule
holidays = self.env['hr.leave'].sudo().search([
('employee_id', 'in', self.ids),
('date_from', '<=', fields.Datetime.now()),
('date_to', '>=', fields.Datetime.now()),
('state', 'not in', ('cancel', 'refuse'))
])
leave_data = {}
for holiday in holidays:
leave_data[holiday.employee_id.id] = {}
leave_data[holiday.employee_id.id]['leave_date_from'] = holiday.date_from.date()
leave_data[holiday.employee_id.id]['leave_date_to'] = holiday.date_to.date()
leave_data[holiday.employee_id.id]['current_leave_state'] = holiday.state
leave_data[holiday.employee_id.id]['current_leave_id'] = holiday.holiday_status_id.id
for employee in self:
employee.leave_date_from = leave_data.get(employee.id, {}).get('leave_date_from')
employee.leave_date_to = leave_data.get(employee.id, {}).get('leave_date_to')
employee.current_leave_state = leave_data.get(employee.id, {}).get('current_leave_state')
employee.current_leave_id = leave_data.get(employee.id, {}).get('current_leave_id')
@api.multi
def _compute_leaves_count(self):
all_leaves = self.env['hr.leave.report'].read_group([
('employee_id', 'in', self.ids),
('holiday_status_id.allocation_type', '!=', 'no'),
('state', '=', 'validate')
], fields=['number_of_days', 'employee_id'], groupby=['employee_id'])
mapping = dict([(leave['employee_id'][0], leave['number_of_days']) for leave in all_leaves])
for employee in self:
employee.leaves_count = float_round(mapping.get(employee.id, 0), precision_digits=2)
@api.multi
def _compute_show_leaves(self):
show_leaves = self.env['res.users'].has_group('hr_holidays.group_hr_holidays_user')
for employee in self:
if show_leaves or employee.user_id == self.env.user:
employee.show_leaves = True
else:
employee.show_leaves = False
@api.multi
def _compute_absent_employee(self):
today_date = datetime.datetime.utcnow().date()
today_start = fields.Datetime.to_string(today_date) # get the midnight of the current utc day
today_end = fields.Datetime.to_string(today_date + relativedelta(hours=23, minutes=59, seconds=59))
data = self.env['hr.leave'].read_group([
('employee_id', 'in', self.ids),
('state', 'not in', ['cancel', 'refuse']),
('date_from', '<=', today_end),
('date_to', '>=', today_start)
], ['employee_id'], ['employee_id'])
result = dict.fromkeys(self.ids, False)
for item in data:
if item['employee_id_count'] >= 1:
result[item['employee_id'][0]] = True
for employee in self:
employee.is_absent_totay = result[employee.id]
@api.multi
def _search_absent_employee(self, operator, value):
today_date = datetime.datetime.utcnow().date()
today_start = fields.Datetime.to_string(today_date) # get the midnight of the current utc day
today_end = fields.Datetime.to_string(today_date + relativedelta(hours=23, minutes=59, seconds=59))
holidays = self.env['hr.leave'].sudo().search([
('employee_id', '!=', False),
('state', 'not in', ['cancel', 'refuse']),
('date_from', '<=', today_end),
('date_to', '>=', today_start)
])
return [('id', 'in', holidays.mapped('employee_id').ids)]
def write(self, values):
res = super(Employee, self).write(values)
if 'parent_id' in values or 'department_id' in values:
hr_vals = {}
if values.get('parent_id') is not None:
hr_vals['manager_id'] = values['parent_id']
if values.get('department_id') is not None:
hr_vals['department_id'] = values['department_id']
holidays = self.env['hr.leave'].search([('state', 'in', ['draft', 'confirm']), ('employee_id', 'in', self.ids)])
holidays.write(hr_vals)
allocations = self.env['hr.leave.allocation'].search([('state', 'in', ['draft', 'confirm']), ('employee_id', 'in', self.ids)])
allocations.write(hr_vals)
return res