summaryrefslogtreecommitdiff
path: root/addons/hr_holidays/models/hr_employee.py
diff options
context:
space:
mode:
authorstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
committerstephanchrst <stephanchrst@gmail.com>2022-05-10 21:51:50 +0700
commit3751379f1e9a4c215fb6eb898b4ccc67659b9ace (patch)
treea44932296ef4a9b71d5f010906253d8c53727726 /addons/hr_holidays/models/hr_employee.py
parent0a15094050bfde69a06d6eff798e9a8ddf2b8c21 (diff)
initial commit 2
Diffstat (limited to 'addons/hr_holidays/models/hr_employee.py')
-rw-r--r--addons/hr_holidays/models/hr_employee.py216
1 files changed, 216 insertions, 0 deletions
diff --git a/addons/hr_holidays/models/hr_employee.py b/addons/hr_holidays/models/hr_employee.py
new file mode 100644
index 00000000..ceb0d2c5
--- /dev/null
+++ b/addons/hr_holidays/models/hr_employee.py
@@ -0,0 +1,216 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+import datetime
+
+from odoo import api, fields, models
+from odoo.tools.float_utils import float_round
+
+
+class HrEmployeeBase(models.AbstractModel):
+ _inherit = "hr.employee.base"
+
+ leave_manager_id = fields.Many2one(
+ 'res.users', string='Time Off',
+ compute='_compute_leave_manager', store=True, readonly=False,
+ help='Select the user responsible for approving "Time Off" of this employee.\n'
+ 'If empty, the approval is done by an Administrator or Approver (determined in settings/users).')
+ remaining_leaves = fields.Float(
+ compute='_compute_remaining_leaves', string='Remaining Paid Time Off',
+ help='Total number of paid time off allocated to this employee, change this value to create allocation/time off request. '
+ 'Total based on all the time off types without overriding limit.')
+ current_leave_state = fields.Selection(compute='_compute_leave_status', string="Current Time Off 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 Time Off 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 Time Off', compute='_compute_remaining_leaves')
+ allocation_count = fields.Float('Total number of days allocated.', compute='_compute_allocation_count')
+ allocation_used_count = fields.Float('Total number of days off used', compute='_compute_total_allocation_used')
+ show_leaves = fields.Boolean('Able to see Remaining Time Off', compute='_compute_show_leaves')
+ is_absent = fields.Boolean('Absent Today', compute='_compute_leave_status', search='_search_absent_employee')
+ allocation_display = fields.Char(compute='_compute_allocation_count')
+ allocation_used_display = fields.Char(compute='_compute_total_allocation_used')
+ hr_icon_display = fields.Selection(selection_add=[('presence_holiday_absent', 'On leave'),
+ ('presence_holiday_present', 'Present but on leave')])
+
+ def _get_date_start_work(self):
+ return self.create_date
+
+ 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 ALL
+ 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
+ s.active = true AND 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())
+
+ def _compute_remaining_leaves(self):
+ remaining = {}
+ if self.ids:
+ remaining = self._get_remaining_leaves()
+ for employee in self:
+ value = float_round(remaining.get(employee.id, 0.0), precision_digits=2)
+ employee.leaves_count = value
+ employee.remaining_leaves = value
+
+ def _compute_allocation_count(self):
+ data = self.env['hr.leave.allocation'].read_group([
+ ('employee_id', 'in', self.ids),
+ ('holiday_status_id.active', '=', True),
+ ('state', '=', 'validate'),
+ ], ['number_of_days:sum', 'employee_id'], ['employee_id'])
+ rg_results = dict((d['employee_id'][0], d['number_of_days']) for d in data)
+ for employee in self:
+ employee.allocation_count = float_round(rg_results.get(employee.id, 0.0), precision_digits=2)
+ employee.allocation_display = "%g" % employee.allocation_count
+
+ def _compute_total_allocation_used(self):
+ for employee in self:
+ employee.allocation_used_count = float_round(employee.allocation_count - employee.remaining_leaves, precision_digits=2)
+ employee.allocation_used_display = "%g" % employee.allocation_used_count
+
+ def _compute_presence_state(self):
+ super()._compute_presence_state()
+ employees = self.filtered(lambda employee: employee.hr_presence_state != 'present' and employee.is_absent)
+ employees.update({'hr_presence_state': 'absent'})
+
+ def _compute_presence_icon(self):
+ super()._compute_presence_icon()
+ employees_absent = self.filtered(lambda employee:
+ employee.hr_icon_display not in ['presence_present', 'presence_absent_active']
+ and employee.is_absent)
+ employees_absent.update({'hr_icon_display': 'presence_holiday_absent'})
+ employees_present = self.filtered(lambda employee:
+ employee.hr_icon_display in ['presence_present', 'presence_absent_active']
+ and employee.is_absent)
+ employees_present.update({'hr_icon_display': 'presence_holiday_present'})
+
+ 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')
+ employee.is_absent = leave_data.get(employee.id) and leave_data.get(employee.id, {}).get('current_leave_state') not in ['cancel', 'refuse', 'draft']
+
+ @api.depends('parent_id')
+ def _compute_leave_manager(self):
+ for employee in self:
+ previous_manager = employee._origin.parent_id.user_id
+ manager = employee.parent_id.user_id
+ if manager and employee.leave_manager_id == previous_manager or not employee.leave_manager_id:
+ employee.leave_manager_id = manager
+ elif not employee.leave_manager_id:
+ employee.leave_manager_id = False
+
+ 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
+
+ def _search_absent_employee(self, operator, value):
+ holidays = self.env['hr.leave'].sudo().search([
+ ('employee_id', '!=', False),
+ ('state', 'not in', ['cancel', 'refuse']),
+ ('date_from', '<=', datetime.datetime.utcnow()),
+ ('date_to', '>=', datetime.datetime.utcnow())
+ ])
+ return [('id', 'in', holidays.mapped('employee_id').ids)]
+
+ @api.model
+ def create(self, values):
+ if 'parent_id' in values:
+ manager = self.env['hr.employee'].browse(values['parent_id']).user_id
+ values['leave_manager_id'] = values.get('leave_manager_id', manager.id)
+ if values.get('leave_manager_id', False):
+ approver_group = self.env.ref('hr_holidays.group_hr_holidays_responsible', raise_if_not_found=False)
+ if approver_group:
+ approver_group.sudo().write({'users': [(4, values['leave_manager_id'])]})
+ return super(HrEmployeeBase, self).create(values)
+
+ def write(self, values):
+ if 'parent_id' in values:
+ manager = self.env['hr.employee'].browse(values['parent_id']).user_id
+ if manager:
+ to_change = self.filtered(lambda e: e.leave_manager_id == e.parent_id.user_id or not e.leave_manager_id)
+ to_change.write({'leave_manager_id': values.get('leave_manager_id', manager.id)})
+
+ old_managers = self.env['res.users']
+ if 'leave_manager_id' in values:
+ old_managers = self.mapped('leave_manager_id')
+ if values['leave_manager_id']:
+ old_managers -= self.env['res.users'].browse(values['leave_manager_id'])
+ approver_group = self.env.ref('hr_holidays.group_hr_holidays_responsible', raise_if_not_found=False)
+ if approver_group:
+ approver_group.sudo().write({'users': [(4, values['leave_manager_id'])]})
+
+ res = super(HrEmployeeBase, self).write(values)
+ # remove users from the Responsible group if they are no longer leave managers
+ old_managers._clean_leave_responsible_users()
+
+ if 'parent_id' in values or 'department_id' in values:
+ today_date = fields.Datetime.now()
+ 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'].sudo().search(['|', ('state', 'in', ['draft', 'confirm']), ('date_from', '>', today_date), ('employee_id', 'in', self.ids)])
+ holidays.write(hr_vals)
+ allocations = self.env['hr.leave.allocation'].sudo().search([('state', 'in', ['draft', 'confirm']), ('employee_id', 'in', self.ids)])
+ allocations.write(hr_vals)
+ return res
+
+class HrEmployeePrivate(models.Model):
+ _inherit = 'hr.employee'
+
+class HrEmployeePublic(models.Model):
+ _inherit = 'hr.employee.public'
+
+ def _compute_leave_status(self):
+ super()._compute_leave_status()
+ self.current_leave_id = False