def calculate_total_hours(self): if self.arrival_time == "#--:--" or self.arrival_time == "00:00" or self.arrival_time == "0:00:00": self.arrival_time = "00:00:00" if self.departure_time == "#--:--" or self.departure_time == "00:00" or self.departure_time == "0:00:00": self.departure_time = "00:00:00" try: totalworkhours = flt(time_diff_in_seconds(self.departure_time,self.arrival_time))/3600 except: try: time = time_diff(self.departure_time,self.arrival_time) totalworkhours = flt(time.hour) + flt(time.minute)/60 + flt(time.second)/3600 except: frappe.throw(_("Possible error in arrival time {0} or departure time {1} for employee {2}").format(self.arrival_time,self.departure_time,self.employee)) self.working_time = totalworkhours weekday = get_datetime(self.att_date).weekday() working_hours = frappe.db.sql("""select working_hours from `tabWorking Hours` where %s between from_date and to_date and docstatus < 2""", (self.att_date)) if working_hours: self.normal_time = flt(working_hours[0][0]) else: self.normal_time = flt(frappe.db.get_single_value("Regulations", "working_hours")) self.overtime = 0 self.overtime_fridays = 0 self.overtime_holidays = 0 self.status = 'Present' if len(self.get_holidays_for_employee(self.att_date,self.att_date)): self.normal_time = 0 self.overtime_holidays = flt(totalworkhours) - flt(self.normal_time) elif weekday == 4: self.normal_time = 0 self.overtime_fridays = flt(totalworkhours) - flt(self.normal_time) else: if totalworkhours > self.normal_time: self.overtime = flt(totalworkhours) - flt(self.normal_time) elif totalworkhours > 2: self.normal_time = totalworkhours elif totalworkhours > 0: frappe.throw(_("Work Hours under 2. Please check the time for employee {0}, date {1}").format(self.employee,self.att_date)) elif totalworkhours < 0: frappe.throw(_("Work Hours negative. Please check the time for employee {0}, date {1}").format(self.employee,self.att_date)) else: if self.arrival_time == "00:00:00" and self.departure_time == "00:00:00": self.normal_time = 0 self.status = 'Absent' else: frappe.throw(_("Please check the time for employee {0}, date {1}").format(self.employee,self.att_date))
def verify_otp(otp_auth_attempt_name, incoming_otp, action): settings = frappe.get_single('CD User Management Settings') frappe.set_user(settings.default_user) otp_auth_attempt_doc = frappe.get_doc("CD OTP Auth Attempt", { "name": otp_auth_attempt_name, "login_status": "OTP Generated" }) verification_time = now_datetime().__str__()[:-7] otp_expiry_limit = settings.otp_expiry_limit_in_mins max_otp_attempts = settings.max_otp_attempts if not (time_diff(verification_time, otp_auth_attempt_doc.generated_time).total_seconds() / 60) <= otp_expiry_limit: otp_auth_attempt_doc.login_status = 'Expired' otp_auth_attempt_doc.save() frappe.local.response.http_status_code = 429 frappe.local.response["message"] = "OTP Expired" if otp_auth_attempt_doc.generated_otp == incoming_otp: otp_auth_attempt_doc.login_status = 'Success' otp_auth_attempt_doc.verify_action = action.replace('_', ' ').title() otp_auth_attempt_doc.save() user = frappe.get_doc( "User", {'mobile_no': otp_auth_attempt_doc.mobile_number}) if action == 'get_reset_password_key': user.reset_password() frappe.local.response[ "reset_password_key"] = user.reset_password_key if action == 'get_api_credentials': frappe.local.response["api_key"] = user.api_key frappe.local.response["api_secret"] = generate_keys( user.name)['api_secret'] else: if len(otp_auth_attempt_doc.failed_attempts) == max_otp_attempts: otp_auth_attempt_doc.login_status = 'Blocked' otp_auth_attempt_doc.save() frappe.local.response.http_status_code = 429 frappe.local.response["message"] = "Maximum Limit Reached" else: otp_auth_attempt_doc.append('failed_attempts', {'failed_incoming_otp': incoming_otp}) otp_auth_attempt_doc.save() frappe.local.response.http_status_code = 401 frappe.local.response["message"] = "Incorrect OTP"
def make_time_sheet(self): if self.calculate_instructor_hour_rate and not frappe.db.exists("Timesheet", {"course_schedule": self.name}): from frappe.utils import time_diff from frappe.utils import get_datetime ts = frappe.new_doc("Timesheet") ts.update({ "employee": frappe.get_value("Instructor", {"name": self.instructor}, "employee"), "company": self.company, "course_schedule": self.name }) ts.append("time_logs", { "activity_type": "Teaching", "hours": round(float(time_diff(self.to_time, self.from_time).total_seconds()) / 3600, 6), "from_time": get_datetime(str(self.schedule_date) + " "+str(self.from_time)), "to_time": get_datetime(str(self.schedule_date) + " "+str(self.to_time)) }) ts.save() ts.submit()
def time_diff_in_minutes(string_ed_date, string_st_date): return time_diff(string_ed_date, string_st_date).total_seconds() / 60
def time_diff_in_hours(start, end): print(start) print(end) print(time_diff(end, start).total_seconds() / 60) return round(time_diff(end, start).total_seconds() / 60, 1)
def get_result_as_list(data, filters): result = [] key_data = frappe._dict() key_list = [] employees = [] dates = [] time_duty_in = to_timedelta("07:30:00") time_duty_in_round = to_timedelta("07:15:00") time_duty_in_from = to_timedelta("07:00:00") time_duty_in_to = to_timedelta("11:00:00") time_lunch_out = to_timedelta("11:45:00") time_lunch_out_round = to_timedelta("11:45:00") time_lunch_out_from = to_timedelta("11:30:01") time_lunch_out_to = to_timedelta("12:15:00") time_lunch_in = to_timedelta("12:30:00") time_lunch_in_round = to_timedelta("12:30:00") time_lunch_in_from = to_timedelta("12:15:01") time_lunch_in_to = to_timedelta("12:45:00") time_duty_out = to_timedelta("17:00:00") time_duty_out_round = to_timedelta("17:15:00") time_duty_out_from = to_timedelta("12:45:01") time_duty_out_to = to_timedelta("20:00:00") time_one_day = 8.75 time_late_in = to_timedelta("07:45:00") time_early_out = to_timedelta("16:59:59") max_morning_float = 4.25 max_evening_float = 4.5 max_day_float = 8.75 for d in data: key = (d.employee, d.c_date) if d.employee not in employees: employees.append(d.employee) if d.c_date not in dates: dates.append(d.c_date) if not key_data.get(key): key_data[key] = frappe._dict() key_data[key]["employee"] = d.employee key_data[key]["employee_name"] = d.employee_name key_data[key]["department"] = d.department key_data[key]["employee_number"] = d.employee_number key_data[key]["c_date"] = d.c_date key_data[key]["c_time"] = d.c_time key_data[key]["duty_in_name"] = "--------" key_data[key]["lunch_out_name"] = "--------" key_data[key]["lunch_in_name"] = "--------" key_data[key]["duty_out_name"] = "--------" c_time = to_timedelta(d.c_time) if not key_data[key].get("all_checkin"): key_data[key]["all_checkin"] = [] key_data[key]["all_checkin"].append(cstr(d.c_time)) if c_time > time_duty_in_from and c_time < time_duty_in_to and not key_data[ key].get("duty_in"): key_data[key]["duty_in_name"] = d.c_name key_data[key]["duty_in"] = d.c_time if c_time > time_lunch_out_from and c_time < time_lunch_out_to and not key_data[ key].get("lunch_out"): key_data[key]["lunch_out_name"] = d.c_name key_data[key]["lunch_out"] = d.c_time if c_time > time_lunch_in_from and c_time < time_lunch_in_to and not key_data[ key].get("lunch_in"): key_data[key]["lunch_in_name"] = d.c_name key_data[key]["lunch_in"] = d.c_time if c_time > time_duty_out_from and c_time < time_duty_out_to and not key_data[ key].get("duty_out"): key_data[key]["duty_out_name"] = d.c_name key_data[key]["duty_out"] = d.c_time for employee in employees: for c_date in dates: key = (employee, c_date) if key_data.get(key): error = "" # if c_date.strftime("%a") == "Sat": # if not (key_data[key].get("duty_in") and key_data[key].get("lunch_out")): # error = "@" # else: # if not (key_data[key].get("duty_in") and key_data[key].get("lunch_out") and key_data[key].get("lunch_in") and key_data[key].get("duty_out")): # error = "@" key_data[key]["morning"] = 0 key_data[key]["lunch"] = 0 key_data[key]["evening"] = 0 key_data[key]["full_duty"] = 0 key_data[key]["ot_hours"] = 0 key_data[key]["late_in"] = "" key_data[key]["early_out"] = "" if key_data[key].get("duty_in"): if key_data[key].get("duty_in") > time_late_in: key_data[key]["late_in"] = "Late In" if key_data[key].get("duty_out"): if key_data[key].get("duty_out") < time_early_out: key_data[key]["early_out"] = "Early Out" row_show = True if filters.get("grace_period"): if filters.get("grace_period") == "Late or Early": if key_data[key]["late_in"] or key_data[key][ "early_out"]: row_show = True else: row_show = False elif (filters.get("grace_period") == key_data[key]["late_in"] or filters.get("grace_period") == key_data[key]["early_out"]): row_show = True else: row_show = False if row_show == True: if key_data[key].get("duty_in"): if key_data[key]["duty_in"] <= time_duty_in_round: key_data[key]["duty_in"] = time_duty_in_round elif key_data[key]["duty_in"] <= time_duty_in: key_data[key]["duty_in"] = time_duty_in if key_data[key].get("lunch_out"): if key_data[key]["lunch_out"] >= time_lunch_out_round: key_data[key]["lunch_out"] = time_lunch_out_round if key_data[key].get("lunch_in"): if key_data[key]["lunch_in"] <= time_lunch_in_round: key_data[key]["lunch_in"] = time_lunch_in_round if key_data[key].get("duty_out"): if key_data[key]["duty_out"] >= time_duty_out: key_data[key]["duty_out"] = time_duty_out if key_data[key].get("lunch_out") and key_data[key].get( "duty_in"): key_data[key]["morning_from"] = key_data[key][ "duty_in"] if key_data[key]["morning_from"] <= time_duty_in: key_data[key]["morning_from"] = time_duty_in key_data[key]["morning_to"] = key_data[key][ "lunch_out"] key_data[key]["morning"] = time_diff( key_data[key].get("morning_from"), key_data[key].get("morning_to")) if key_data[key].get("lunch_in") and key_data[key].get( "lunch_out"): key_data[key]["lunch"] = time_diff( key_data[key].get("lunch_in"), key_data[key].get("lunch_out")) if key_data[key].get("duty_out") and key_data[key].get( "lunch_in"): key_data[key]["evening"] = time_diff( key_data[key].get("duty_out"), key_data[key].get("lunch_in")) if key_data[key].get( "duty_in") and not key_data[key].get("lunch_out"): key_data[key]["error"] = "@" elif key_data[key].get( "lunch_out") and not key_data[key].get("duty_in"): key_data[key]["error"] = "@" elif key_data[key].get( "lunch_in") and not key_data[key].get("duty_out"): key_data[key]["error"] = "@" elif key_data[key].get( "duty_out") and not key_data[key].get("lunch_in"): key_data[key]["error"] = "@" if key_data[key].get("morning") and key_data[key].get( "evening"): key_data[key]["full_duty"] = 1 elif key_data[key].get("morning") or key_data[key].get( "evening"): key_data[key]["full_duty"] = 0.5 key_data[key]["total_hours_float"] = 0 key_data[key]["morning_float"] = 0 key_data[key]["lunch_float"] = 0 key_data[key]["evening_float"] = 0 key_data[key]["ot_hours_float"] = 0 if key_data[key].get("morning") != 0: key_data[key]["morning_float"] = key_data[key].get( "morning").seconds / (60 * 60) if key_data[key]["morning_float"] > max_morning_float: key_data[key]["morning_float"] = max_morning_float # key_data[key]["morning_float"] = round_time_up(key_data[key]["morning_float"]) if key_data[key].get("lunch") != 0: key_data[key]["lunch_float"] = key_data[key].get( "lunch").seconds / (60 * 60) if key_data[key].get("evening") != 0: key_data[key]["evening_float"] = key_data[key].get( "evening").seconds / (60 * 60) if key_data[key]["evening_float"] > max_evening_float: key_data[key]["evening_float"] = max_evening_float # key_data[key]["evening_float"] = round_time_up(key_data[key]["evening_float"]) key_data[key]["total_hours_float"] = key_data[key][ "morning_float"] + key_data[key]["evening_float"] if key_data[key].get("morning") and key_data[key].get( "evening"): if key_data[key][ "total_hours_float"] - time_one_day > 0: key_data[key]["ot_hours_float"] = key_data[key][ "total_hours_float"] - time_one_day key_data[key]["all_checkin"] = " || ".join( key_data[key]["all_checkin"]) key_data[key]["morning"] = key_data[key].get( "morning") or "" key_data[key]["lunch"] = key_data[key].get("lunch") or "" key_data[key]["evening"] = key_data[key].get( "evening") or "" key_data[key]["total_hours_float"] = key_data[key].get( "total_hours_float") if ( key_data[key].get("total_hours_float") > 0) else "" key_data[key]["full_duty"] = key_data[key].get( "full_duty") or "" key_data[key]["ot_hours"] = key_data[key].get( "ot_hours") or "" key_data[key]["duty_in"] = key_data[key].get( "duty_in") or "--------" key_data[key]["lunch_out"] = key_data[key].get( "lunch_out") or "--------" key_data[key]["lunch_in"] = key_data[key].get( "lunch_in") or "--------" key_data[key]["duty_out"] = key_data[key].get( "duty_out") or "--------" row = key_data[key] result.append(row) return result
def add_overtime(self, att_over, to_time, att_from_time, employee_start_time, employee_end_time): #if is_overtime_exceeded(self.employee, self.attendance_date): # frappe.throw(_("Overtime is exceeded!")) overtime_max_minutes = frappe.db.get_value("HR Settings", None, "overtime_max_minutes") if not overtime_max_minutes: frappe.throw(_("Enter the value of max overtime in HR settings")) total_att = time_diff(str(self.departure_time), str(self.attendance_time)) shift_att = time_diff(str(employee_end_time), str(employee_start_time)) diff = time_diff_in_hours(str(total_att), str(shift_att)) att_time = frappe.db.get_value( "Attendance", { "docstatus": ("<", 2), "employee": self.employee, "attendance_date": self.attendance_date }, "attendance_time") if not att_time: att_time = self.attendance_time dep_time = att_time + shift_att dep_timedate = dt.datetime.combine( getdate(self.attendance_date), dt.datetime.strptime(str(dep_time), '%H:%M:%S').time()) total_exit = self.validate_permissions() #frappe.msgprint(str(total_exit)) discount_permissions_from_attendance_hours = frappe.db.get_value( "HR Settings", None, "discount_permissions_from_attendance_hours") if discount_permissions_from_attendance_hours and total_exit != 0.0: if diff > total_exit: diff = diff - total_exit else: diff = total_exit - diff if self.attendance_time: if total_att > shift_att and diff * 60 > float( overtime_max_minutes): if att_over: over_det = frappe.get_doc('Timesheet', att_over) if frappe.db.exists( 'Timesheet Detail', { 'parent': over_det.name, 'activity_type': _('Auto Entry: Overtime Attendance') }): time_det = frappe.get_doc( 'Timesheet Detail', { 'parent': over_det.name, 'activity_type': _('Auto Entry: Overtime Attendance') }) time_det.update({ 'from_time': dep_timedate, 'to_time': to_time, 'hours': diff }) #time_det.from_time = dep_timedate #time_det.to_time = to_time time_det.flags.ignore_validate = True time_det.flags.ignore_validate_update_after_submit = True time_det.save(ignore_permissions=True) update_overtime_total_hrs(over_det) else: over_det.update({ 'time_logs': [{ 'activity_type': _('Auto Entry: Overtime Attendance'), 'from_time': dep_timedate, 'to_time': to_time, 'hours': diff }] }) over_det.flags.ignore_validate = True over_det.flags.ignore_validate_update_after_submit = True over_det.save(ignore_permissions=True) update_overtime_total_hrs(over_det) else: overtime = frappe.new_doc('Timesheet') overtime.update({ 'name': self.employee, 'employee': self.employee, 'start_date': getdate(self.attendance_date), 'to_date': getdate(self.attendance_date), 'time_logs': [{ 'activity_type': _('Auto Entry: Overtime Attendance'), 'from_time': dep_timedate, 'to_time': to_time, 'hours': diff }], 'type': 'compensatory', 'docstatus': 0, 'workflow_state': 'Pending Request' }) overtime.insert(ignore_permissions=True) return "done"
def validate_attendance_date(self): att_time = frappe.db.get_value( "Attendance", { "docstatus": ("<", 2), "employee": self.employee, "attendance_date": self.departure_date }, "attendance_time") departure_date = self.departure_date if self.departure_date and (isinstance(self.departure_date, str) or isinstance(self.departure_date, unicode)): departure_date = datetime.datetime.strptime( self.departure_date, '%Y-%m-%d') att_time_next = frappe.db.get_value( "Attendance", { "docstatus": ("<", 2), "employee": self.employee, "attendance_date": (departure_date - timedelta(days=1)) }, "attendance_time") if not att_time and att_time_next: att_time = att_time_next elif not att_time and not att_time_next: frappe.throw(_("Attendance does not exist")) attendance_day = calendar.day_name[getdate( self.departure_date).weekday()] attendance_day_next = calendar.day_name[ getdate(self.departure_date).weekday() - 1] employee_work_shift = frappe.db.get_value("Employee", self.employee, "work_shift") employee_end_time = frappe.db.get_value("Work Shift Details", { "parent": employee_work_shift, "day": attendance_day }, "end_work") employee_end_time_next = frappe.db.get_value( "Work Shift Details", { "parent": employee_work_shift, "day": attendance_day_next, "next_day": 1 }, "end_work") #if not employee_end_time and not employee_end_time_next: # frappe.throw(_("End Time Work Shift does not exist for that day")) #if get_time(self.departure_time) > get_time(employee_end_time): # frappe.throw(_("Departure time can not be more than employee's end time shift")) if self.departure_time: exit_per = frappe.db.get_value( "Exit permission", { 'employee': self.employee, 'permission_type': 'Exit with return', 'permission_date': self.departure_date, 'type': 'Exit', 'docstatus': ("<", 2) }, "name") ret_per = frappe.db.get_value( "Exit permission", { 'employee': self.employee, 'permission_type': 'Exit with return', 'permission_date': self.departure_date, 'type': 'Return', 'docstatus': ("<", 2) }, ["name", "to_date"]) if exit_per and not ret_per: frappe.throw( _("Not Allowed! You have an Exit permission with no return" )) if ret_per: if get_time(self.departure_time) < get_time(ret_per[1]): frappe.throw( _("Departure time can not be less than return time permission" )) day = calendar.day_name[getdate(self.departure_date).weekday()] day_next = calendar.day_name[getdate(self.departure_date).weekday() - 1] employee_work_shift = frappe.db.get_value("Employee", self.employee, "work_shift") employee_start_time = frappe.db.get_value("Work Shift Details", { "parent": employee_work_shift, "day": day }, "start_work") employee_end_time = frappe.db.get_value("Work Shift Details", { "parent": employee_work_shift, "day": day }, "end_work") employee_start_time_next = frappe.db.get_value("Work Shift Details", { "parent": employee_work_shift, "day": day_next, "next_day": 1 }, "start_work") employee_end_time_next = frappe.db.get_value("Work Shift Details", { "parent": employee_work_shift, "day": day_next, "next_day": 1 }, "end_work") #shift_diff = str(time_diff_in_hours(employee_end_time,employee_start_time)) #if not employee_start_time and not employee_start_time_next: # frappe.throw(_("Start Time Work Shift does not exist for that day")) if employee_end_time_next: att_from_time = frappe.db.sql( 'select TIMESTAMP(%s , %s)', (self.departure_date, employee_end_time_next))[0][0] if employee_end_time: att_from_time = frappe.db.sql( 'select TIMESTAMP(%s , %s)', (self.departure_date, employee_end_time))[0][0] if employee_end_time_next: to_time = frappe.db.sql( 'select TIMESTAMP(%s , %s)', (self.departure_date, self.departure_time))[0][0] from_time = frappe.db.sql( 'select TIMESTAMP(%s , %s)', (departure_date - timedelta(days=1), att_time))[0][0] else: to_time = frappe.db.sql( 'select TIMESTAMP(%s , %s)', (self.departure_date, self.departure_time))[0][0] from_time = frappe.db.sql('select TIMESTAMP(%s , %s)', (self.departure_date, att_time))[0][0] #### In Holiday >>overtime ### holiday_list = frappe.db.get_value("Employee", self.employee, "holiday_list") att_over = frappe.db.get_value( "Timesheet", { "employee": self.employee, "start_date": self.departure_date, "docstatus": ("<", 2) }, "name") over_diff = str(time_diff_in_hours(to_time, from_time)) is_holiday = False if holiday_list: holidays = frappe.get_all("Holiday", fields=["holiday_date"], filters={'parent': holiday_list}) for holiday in holidays: if holiday.holiday_date == getdate(self.departure_date): is_holiday = True overtime_max_minutes = frappe.db.get_value("HR Settings", None, "overtime_max_minutes") if not overtime_max_minutes: frappe.throw( _("Enter the value of max overtime in HR settings")) #if is_overtime_exceeded(self.employee, self.departure_date): # frappe.throw(_("Overtime is exceeded!")) diff = 0 if is_holiday: if employee_start_time_next: total_att = datetime.timedelta(hours=24) - time_diff( str(att_time), str(self.departure_time)) shift_att = datetime.timedelta(hours=24) - time_diff( str(employee_start_time_next), str(employee_end_time)) diff = time_diff_in_hours(str(total_att), str(shift_att)) else: total_att = time_diff(str(self.departure_time), str(att_time)) shift_att = time_diff(str(employee_end_time), str(employee_start_time)) #diff = time_diff_in_hours(str(total_att),str(shift_att)) diff = 0 if is_holiday and total_att > shift_att and diff * 60 > float( overtime_max_minutes): dep_time = att_time + shift_att if employee_start_time_next: dep_timedate = frappe.db.sql( 'select TIMESTAMP(%s , %s)', ((departure_date - timedelta(days=1)), dep_time))[0][0] #dep_timedate= dt.datetime.combine(getdate(self.departure_date), dt.datetime.strptime(str(dep_time), '%H:%M:%S.%f').time()) else: dep_timedate = frappe.db.sql( 'select TIMESTAMP(%s , %s)', (self.departure_date, dep_time))[0][0] if att_over: over_det = frappe.get_doc('Timesheet', att_over) if frappe.get_value( 'Timesheet Detail', { 'parent': over_det.name, 'activity_type': _('Auto Entry: Overtime Attendance') }): time_det = frappe.get_doc( 'Timesheet Detail', { 'parent': over_det.name, 'activity_type': _('Auto Entry: Overtime Attendance') }) time_det.update({ 'from_time': dep_timedate, 'to_time': to_time, 'hours': diff }) time_det.flags.ignore_validate = True time_det.flags.ignore_validate_update_after_submit = True time_det.save(ignore_permissions=True) from erpnext.hr.doctype.employee_edit_time.employee_edit_time import update_overtime_total_hrs update_overtime_total_hrs(over_det) else: hol_overtime = frappe.new_doc('Timesheet') hol_overtime.update({ 'name': self.employee, 'employee': self.employee, 'start_date': getdate(self.departure_date), 'to_date': getdate(self.departure_date), 'time_logs': [{ 'activity_type': _('Auto Entry: Overtime Attendance'), 'from_time': dep_timedate, 'to_time': to_time, 'hours': diff }], 'type': 'compensatory', 'docstatus': 0, 'workflow_state': 'Pending Request' }) hol_overtime.insert(ignore_permissions=True) else: self.add_overtime(att_time, att_over, to_time, att_from_time, employee_start_time, employee_end_time, employee_start_time_next) ########Early Departure early_departure_in_minutes = frappe.db.get_value( "HR Settings", None, "early_departure_in_minutes") if not early_departure_in_minutes: frappe.throw( _("Add a value for Early Departure In Minutes in HR Settings")) if self.is_new( ) and employee_end_time and self.departure_time and self.docstatus < 2 and not is_holiday: diff = 0 #if get_time(self.departure_time) < get_time(employee_end_time): #diff_time = frappe.db.sql("select format(((TIME_TO_SEC('%s')-TIME_TO_SEC('%s'))/60),0)" %(str(employee_end_time), str(self.departure_time))) if employee_start_time_next: total_att = datetime.timedelta(hours=24) - time_diff( str(att_time), str(self.departure_time)) shift_att = datetime.timedelta(hours=24) - time_diff( str(employee_start_time_next), str(employee_end_time)) diff = time_diff_in_hours(str(shift_att), str(total_att)) else: total_att = time_diff(str(self.departure_time), str(att_time)) shift_att = time_diff(str(employee_end_time), str(employee_start_time)) diff = time_diff_in_hours(str(shift_att), str(total_att)) #frappe.msgprint(str(diff)) if total_att < shift_att: if abs(diff * 60) > float(early_departure_in_minutes): doc = frappe.new_doc('Exit permission') doc.update({ 'employee': self.employee, 'permission_date': getdate(self.departure_date), 'from_date': get_time(att_time), 'to_date': get_time(self.departure_time), 'reason': _("System Auto Entry: Early Departure"), 'permission_type': "Early Departure", 'early_diff': round(diff, 2), 'docstatus': 0, 'workflow_state': 'Pending Request' }) doc.insert(ignore_permissions=True)
def add_overtime(self, att_time, att_over, to_time, att_from_time, employee_start_time, employee_end_time, employee_start_time_next): diff = 0 overtime_max_minutes = frappe.db.get_value("HR Settings", None, "overtime_max_minutes") if not overtime_max_minutes: frappe.throw(_("Enter the value of max overtime in HR settings")) #if is_overtime_exceeded(self.employee, self.departure_date): # frappe.throw(_("Overtime is exceeded!")) if employee_start_time_next: total_att = datetime.timedelta(hours=24) - time_diff( str(att_time), str(self.departure_time)) shift_att = datetime.timedelta(hours=24) - time_diff( str(employee_start_time_next), str(employee_end_time)) diff = time_diff_in_hours(str(total_att), str(shift_att)) else: total_att = time_diff(str(self.departure_time), str(att_time)) shift_att = time_diff(str(employee_end_time), str(employee_start_time)) #diff = time_diff_in_hours(str(total_att),str(shift_att)) diff = 0 dep_time = att_time + shift_att dep_timedate = frappe.db.sql('select TIMESTAMP(%s , %s)', (self.departure_date, dep_time))[0][0] #dep_timedate= dt.datetime.combine(getdate(self.departure_date), dt.datetime.strptime(str(dep_time), '%H:%M:%S.%f').time()) total_exit = self.validate_permissions() #frappe.msgprint("bb "+str(total_exit)) discount_permissions_from_attendance_hours = frappe.db.get_value( "HR Settings", None, "discount_permissions_from_attendance_hours") if discount_permissions_from_attendance_hours and total_exit != 0.0: if diff > total_exit: diff = diff - total_exit else: diff = total_exit - diff #### attendance > shift time #### if att_time: #diff_time=str(time_diff_in_hours(self.departure_time,att_time)) #diff_time = frappe.db.sql("select format(((TIME_TO_SEC('%s')-TIME_TO_SEC('%s'))/60),0)" %(str(self.departure_time), str(att_from_time)))[0][0] #shift_diff1 = frappe.db.sql("select format(((TIME_TO_SEC('%s')-TIME_TO_SEC('%s'))/60),0)" %(str(employee_end_time), str(employee_start_time)))[0][0] #frappe.msgprint(str(rem_dt)) #frappe.msgprint(str(get_time(self.departure_time)+to_timedelta(diff_dep_shift))) #if shift_diff1 and float(diff_time) > 0: if total_att > shift_att and diff * 60 > float( overtime_max_minutes): if att_over: over_det = frappe.get_doc('Timesheet', att_over) if frappe.get_value( 'Timesheet Detail', { 'parent': over_det.name, 'activity_type': _('Auto Entry: Overtime Attendance') }): time_det = frappe.get_doc( 'Timesheet Detail', { 'parent': over_det.name, 'activity_type': _('Auto Entry: Overtime Attendance') }) time_det.update({ 'from_time': dep_timedate.replace(microsecond=0), 'to_time': to_time, 'hours': diff }) time_det.flags.ignore_validate = True time_det.flags.ignore_validate_update_after_submit = True time_det.save(ignore_permissions=True) from erpnext.hr.doctype.employee_edit_time.employee_edit_time import update_overtime_total_hrs update_overtime_total_hrs(over_det) else: overtime = frappe.new_doc('Timesheet') overtime.update({ 'name': self.employee, 'employee': self.employee, 'start_date': getdate(self.departure_date), 'to_date': getdate(self.departure_date), 'time_logs': [{ 'activity_type': _('Auto Entry: Overtime Attendance'), 'from_time': dep_timedate.replace(microsecond=0), 'to_time': to_time, 'hours': diff }], 'type': 'compensatory', 'docstatus': 0, 'workflow_state': 'Pending Request' }) overtime.insert(ignore_permissions=True) return "done"
frappe.throw( _("Possible error in arrival time {0} for employee {1}"). format(self.arrival_time, self.employee, cstr(e))) except: frappe.throw( _("Possible error in arrival time {0} for employee {1}"). format(self.arrival_time, self.employee)) totalworkhours = 0 try: totalworkhours = flt( time_diff_in_seconds(self.departure_time, self.arrival_time)) / 3600 except: try: time = time_diff(self.departure_time, self.arrival_time) totalworkhours = flt(time.hour) + flt(time.minute) / 60 + flt( time.second) / 3600 except: frappe.throw( _("Possible error in arrival time {0} or departure time {1} for employee {2}" ).format(self.arrival_time, self.departure_time, self.employee)) if totalworkhours < 0: frappe.throw( _("Working time cannot be negative. Please check arrival time {0} or departure time {1} for employee {2} on date {3}" ).format(self.arrival_time, self.departure_time, self.employee, self.attendance_date)) elif totalworkhours > 24: frappe.throw(
def mark_attendance(**args): args = frappe._dict(args) employee = args.get("userid") posix_timestamp = args.get("att_time") att_type = args.get("att_type") stgid = args.get("stgid") token = args.get("auth_token") # create the custom response response = Response() response.mimetype = 'text/plain' response.charset = 'utf-8' response.data = "ok" if not employee or not posix_timestamp or not stgid or not token: log_error("invalid data", args) return response # TODO validate URL/IP if provided if not frappe.db.exists("Custom Biometric Unit Integration Settings", {"device_id": stgid}): log_error("settings for device missing", args) return response auth_token = frappe.db.get_value( "Custom Biometric Unit Integration Settings", {"device_id": stgid}, "auth_token") if not auth_token or (auth_token and auth_token != token): log_error("device auth error", args) return response if not frappe.db.exists("Employee", employee): log_error("employee not found", args) return response try: timestamp = float(posix_timestamp) tz = pytz.timezone('UTC') dt = datetime.fromtimestamp(timestamp, tz) dt = get_datetime_str(dt) date = getdate(dt) except: log_error("invalid timestamp", args) return response attendance = None company = frappe.db.get_value("Employee", employee, "company") attendance_name = frappe.db.exists("Attendance", { "employee": employee, "attendance_date": date }) if attendance_name: attendance = frappe.get_doc("Attendance", attendance_name) if attendance: if attendance.docstatus == 1: log_error("attendance already submitted", args) return response else: attendance.cams_out = dt attendance.cams_out_device = stgid else: try: attendance = frappe.get_doc({ "doctype": "Attendance", "employee": employee, "attendance_date": date, "company": company, "status": "Present", "cams_in": dt, "cams_in_device": stgid, "cams_spend": None }).insert(ignore_permissions=1) frappe.db.commit() return response except: log_error("insert attendance", args) return response if attendance.cams_in and attendance.cams_out: attendance.cams_spend = time_diff(attendance.cams_out, attendance.cams_in) try: attendance.db_update() frappe.db.commit() except: log_error("update attendance", args) return response return response
def get_shift_hours(toTime, fromTime): hours = time_diff(toTime, fromTime) return hours
def time_diff_in_minutes(in_time, s_time): return time_diff(in_time, s_time).total_seconds() / 60