tictac/itis_hr_leave_extend/wizard/hr_sick_leave.py

279 lines
13 KiB
Python

# -*- coding: utf-8 -*-
##############################################################################
#
# TicTac allows several HR functionalities. This program bases on Odoo v. 8. Copyright
# (C) 2018 ITIS www.itis.de commissioned by Wikimedia Deutschland e.V.
#
# This program is free software: you can redistribute it and/or modify it under the
# terms of the GNU Affero General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE. See the GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License along with
# this program. If not, see <https://www.gnu.org/licenses/>.
#
##############################################################################
from openerp import models, fields, api, _
from openerp.exceptions import Warning
from openerp.tools import DEFAULT_SERVER_DATETIME_FORMAT, DEFAULT_SERVER_DATE_FORMAT
from datetime import datetime, timedelta
from openerp import SUPERUSER_ID
from dateutil.relativedelta import relativedelta
class hr_sick_leave(models.TransientModel):
_name = 'hr.sick.leave'
start_date = fields.Datetime('Start Date')
end_date = fields.Datetime('End Date')
@api.multi
def confirm_sick_time(self):
""" This function is use to fill the timesheet when employee is sick.
"""
hr_employee_env = self.env['hr.employee']
sheet_obj = self.env['hr_timesheet_sheet.sheet']
timesheet_obj = self.pool.get('hr.analytic.timesheet')
active_ids = self.env.context.get('active_ids')
if active_ids:
account_id = self.env.user.company_id and self.env.user.company_id.sick_account_id or False
if not account_id:
raise Warning(_('Please set the analytic account for Sick Leaves.\nPlease contact your administrator for the same.'))
for hr_employee_brw in hr_employee_env.browse(active_ids):
res = self.count_day_sickleave(hr_employee_brw)
timesheets = sheet_obj.search([("employee_id", '=', hr_employee_brw.id)])
#for sick_leave_rec in res:
for key, value in res.iteritems():
cur_day_timesheeht_found = False
cur_day = datetime.strptime(key, DEFAULT_SERVER_DATE_FORMAT)
for timesheet in timesheets:
ts_date_from = datetime.strptime(timesheet.date_from, DEFAULT_SERVER_DATE_FORMAT)
ts_date_to = datetime.strptime(timesheet.date_to, DEFAULT_SERVER_DATE_FORMAT)
if cur_day >= ts_date_from and cur_day <= ts_date_to:
cur_day_timesheeht_found = True
# print"Final Timesheet----",timesheet
# if timesheet.state != 'draft':
# raise Warning(_('The Time period is allready closed. \n Please contact the Human Resource Team if the leave request should be confirmed nevertheless'))
# timesheet_ids = timesheet_obj.search(self.env.cr,self.env.uid,[('name','like','Sick Leave on:'),('sheet_id','=',timesheet.id),('user_id','=',hr_employee_brw.user_id.id)])
# if timesheet_ids:
# timesheet_obj.unlink(self.env.cr,self.env.uid,timesheet_ids)
ana_ts_id = self.create_sickleave_timesheet(account_id, timesheet, value, key,hr_employee_brw)
#hl_ts_rec.write({'timesheet_id': ana_ts_id[0], 'sheet_id': timesheet.id})
if cur_day_timesheeht_found == False:
self.create_future_timesheet(cur_day,account_id, value, key,hr_employee_brw)
return True
def create_future_timesheet(self,cur_day,account_id, value, key,hr_employee_brw):
"""
Use to create a future timesheet base upon the user configuration
"""
hr_timesheet =self.env['hr_timesheet_sheet.sheet']
timesheet_start_date = self.get_timesheet_start_date(cur_day)
timesheet_end_date =self.get_timesheet_end_date(cur_day)
timesheets = hr_timesheet.search([("employee_id", '=', hr_employee_brw.id),("date_from", '=', timesheet_start_date),("date_to", '=', timesheet_end_date)])
# print"START----------END--------",timesheet_start_date,timesheet_end_date,timesheets
if not timesheets:
timesheets = hr_timesheet.create({'employee_id':hr_employee_brw.id,'date_from':timesheet_start_date,'date_to':timesheet_end_date})
self.create_sickleave_timesheet(account_id, timesheets, value, key,hr_employee_brw)
def get_timesheet_start_date(self,cur_day):
user = self.env['res.users'].browse(self.env.uid)
r = user.company_id and user.company_id.timesheet_range or 'month'
if r == 'month':
timesheet_start_date = cur_day.strftime('%Y-%m-01')
elif r == 'week':
timesheet_start_date = (cur_day+ relativedelta(weekday=0, days=-6)).strftime('%Y-%m-%d')
elif r == 'year':
timesheet_start_date = cur_day.strftime('%Y-01-01')
else:
timesheet_start_date = cur_day
return timesheet_start_date
def get_timesheet_end_date(self,cur_day):
user = self.env['res.users'].browse(self.env.uid)
r = user.company_id and user.company_id.timesheet_range or 'month'
if r == 'month':
timesheet_end_date = (cur_day+ relativedelta(months=+1, day=1, days=-1)).strftime('%Y-%m-%d')
elif r == 'week':
timesheet_end_date = (cur_day+ relativedelta(weekday=6)).strftime('%Y-%m-%d')
elif r == 'year':
timesheet_end_date = cur_day.strftime('%Y-12-31')
else:
timesheet_end_date = cur_day
return timesheet_end_date
@api.one
def create_sickleave_timesheet(self, account_id, sheet, duration, day,hr_employee_brw):
"""
This function is use to create analytic timesheet based on the sick date and other inputs
:param account_id: analytic account id
:param sheet: timesheet id
:param duration: planned time of the leave
:param day: date of the leave
:param hr_employee_brw: employee browse record
:return: created record for the analytic timesheet
"""
timesheet_obj = self.pool.get('hr.analytic.timesheet')
cr = self.env.cr
uid = self.env.uid
emp_obj = self.env['hr.employee']
hour = duration
res = timesheet_obj.default_get(cr, uid, ['product_id','product_uom_id'])
if not res['product_uom_id']:
raise Warning(_('User Error! \nPlease define cost unit for this employee.'))
up = timesheet_obj.on_change_unit_amount(cr, uid, False, res['product_id'], hour,False, res['product_uom_id'])['value']
res['name'] = "Sick Leave on:" + day
res['account_id'] = account_id.id
res['unit_amount'] = hour
emp_journal = emp_obj.search([('user_id', '=', hr_employee_brw.user_id.id)]).journal_id
res['journal_id'] = emp_journal and emp_journal.id or False
res.update(up)
up = timesheet_obj.on_change_account_id(cr, uid, [], res['account_id']).get('value', {})
res.update(up)
res.update({
'date': day,
'user_id': hr_employee_brw.user_id.id,
'sheet_id': sheet.id,
})
return timesheet_obj.create(cr, SUPERUSER_ID, res)
def count_day_sickleave(self,hr_employee_brw):
res = {}
date_from = datetime.strptime(self.start_date, DEFAULT_SERVER_DATETIME_FORMAT)
date_to = datetime.strptime(self.end_date, DEFAULT_SERVER_DATETIME_FORMAT)
same_day = self.check_same_day(date_from, date_to)
temp_date = date_from
day_hours = 0.0
weekday = temp_date.weekday()
for contract in hr_employee_brw.contract_ids:
cont_start_date = datetime.strptime(contract.date_start, DEFAULT_SERVER_DATE_FORMAT)
if not contract.date_end:
if cont_start_date <= temp_date:
if same_day:
cur_hour = self.get_sameday_hours(date_from, date_to, contract.working_hours.attendance_ids)
day_hours += cur_hour
day_str = datetime.strftime(temp_date, DEFAULT_SERVER_DATETIME_FORMAT).split(" ")[0]
new_hour = res.get(day_str, 0.0) + cur_hour
res.update({day_str: new_hour})
else:
fday_cur_hour = self.get_fday_hours(date_from, contract.working_hours.attendance_ids)
day_hours += fday_cur_hour
lday_cur_hour = self.get_lday_hours(date_to, contract.working_hours.attendance_ids)
day_hours += lday_cur_hour
fday_str = datetime.strftime(date_from, DEFAULT_SERVER_DATETIME_FORMAT).split(" ")[0]
fday_new_hour = res.get(fday_str, 0.0) + fday_cur_hour
res.update({fday_str: fday_new_hour})
lday_str = datetime.strftime(date_to, DEFAULT_SERVER_DATETIME_FORMAT).split(" ")[0]
lday_new_hour = res.get(lday_str, 0.0) + lday_cur_hour
res.update({lday_str: lday_new_hour})
else:
cont_end_date = datetime.strptime(contract.date_end, DEFAULT_SERVER_DATE_FORMAT)
cont_end_date += timedelta(days=1)
if cont_start_date <= temp_date and cont_end_date >= temp_date:
if same_day:
cur_hour = self.get_sameday_hours(date_from, date_to, contract.working_hours.attendance_ids)
day_hours += cur_hour
day_str = datetime.strftime(temp_date, DEFAULT_SERVER_DATETIME_FORMAT).split(" ")[0]
new_hour = res.get(day_str, 0.0) + cur_hour
res.update({day_str: new_hour})
else:
fday_cur_hour = self.get_fday_hours(date_from, contract.working_hours.attendance_ids)
day_hours += fday_cur_hour
lday_cur_hour = self.get_lday_hours(date_to, contract.working_hours.attendance_ids)
day_hours += lday_cur_hour
fday_str = datetime.strftime(date_from, DEFAULT_SERVER_DATETIME_FORMAT).split(" ")[0]
fday_new_hour = res.get(fday_str, 0.0) + fday_cur_hour
res.update({fday_str: fday_new_hour})
lday_str = datetime.strftime(date_to, DEFAULT_SERVER_DATETIME_FORMAT).split(" ")[0]
lday_new_hour = res.get(lday_str, 0.0) + lday_cur_hour
res.update({lday_str: lday_new_hour})
date_from = datetime.strptime(self.start_date.split(" ")[0], DEFAULT_SERVER_DATE_FORMAT)
date_to = datetime.strptime(self.end_date.split(" ")[0], DEFAULT_SERVER_DATE_FORMAT)
temp_date = date_from
temp_date += timedelta(days=1)
while temp_date < date_to:
weekday = temp_date.weekday()
for contract in hr_employee_brw.contract_ids:
cont_start_date = datetime.strptime(contract.date_start, DEFAULT_SERVER_DATE_FORMAT)
cont_end_date = False
if not contract.date_end:
if cont_start_date <= temp_date:
cur_hour = self.get_hours(weekday, contract.working_hours.attendance_ids)
day_hours += cur_hour
day_str = datetime.strftime(temp_date, DEFAULT_SERVER_DATE_FORMAT).split(" ")[0]
new_hour = res.get(day_str, 0.0) + cur_hour
res.update({day_str: new_hour})
else:
cont_end_date = datetime.strptime(contract.date_end, DEFAULT_SERVER_DATE_FORMAT)
if cont_start_date <= temp_date and cont_end_date >= temp_date:
cur_hour = self.get_hours(weekday, contract.working_hours.attendance_ids)
day_hours += cur_hour
day_str = datetime.strftime(temp_date, DEFAULT_SERVER_DATE_FORMAT).split(" ")[0]
new_hour = res.get(day_str, 0.0) + cur_hour
res.update({day_str: new_hour})
temp_date += timedelta(days=1)
return res
def check_same_day(self, date_from, date_to):
return date_from.date() == date_to.date()
def get_sameday_hours(self, date_from, date_to, atten_ids):
weekday = date_from.weekday()
res = self.get_hours(weekday, atten_ids)
return res
def get_lday_hours(self, date_to, atten_ids):
weekday = date_to.weekday()
return self.get_hours(weekday, atten_ids)
def get_fday_hours(self, date_from, atten_ids):
weekday = date_from.weekday()
return self.get_hours(weekday, atten_ids)
def get_hours(self, weekday, atten_ids):
res = 0.0
for atten in atten_ids:
if int(atten.dayofweek) == weekday:
res += atten.hour_to - atten.hour_from
return res