# -*- 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 . # ############################################################################## 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