def create_pre_post_document(doc): if doc.nursing_tasks: for nursing_task in doc.nursing_tasks: if not nursing_task.nursing_task_reference: create_nursing_task(doc, nursing_task) if doc.investigations: for investigation in doc.investigations: if not investigation.lab_test_reference: lab_test = create_lab_test_doc( True, doc.practitioner, frappe.get_doc("Patient", doc.patient), frappe.get_doc("Lab Test Template", investigation.lab_test)) lab_test.reference_dt = doc.doctype lab_test.reference_dn = doc.name lab_test.expected_result_date = doc.start_date if doc.start_time and investigation.expected_time and investigation.expected_time > 0: if investigation.task == "After": lab_test.expected_result_time = to_timedelta( doc.start_time) + datetime.timedelta( seconds=investigation.expected_time * 60) elif investigation.task == "Before": lab_test.expected_result_time = to_timedelta( doc.start_time) - datetime.timedelta( seconds=investigation.expected_time * 60) lab_test.save(ignore_permissions=True)
def validate_date(self): if self.date > today(): frappe.throw( "Did you fix the Flux Capacitor ? \n Meeting Date is Greater than today." ) if to_timedelta(self.start_time) > to_timedelta(self.end_time): frappe.throw("Start Time cannot be greater than End Time.")
def on_update(self): from frappe.utils import to_timedelta shift = frappe.db.get_value("Employee", self.employee, "shift_type") shift_type = frappe.get_doc("Shift Type", {"name": shift}) total_hours = to_timedelta(shift_type.end_time) - to_timedelta(shift_type.start_time) if total_hours: total_sec = frappe.db.sql( """select TIME_TO_SEC(%s) from `tabSalary Structure Assignment` where name = %s""",[total_hours,self.name])[0][0] self.total_min = total_sec / 60
def is_within_operating_hours(workstation, operation, from_datetime, to_datetime): operation_length = time_diff_in_seconds(to_datetime, from_datetime) workstation = frappe.get_doc("Workstation", workstation) for working_hour in workstation.working_hours: slot_length = (to_timedelta(working_hour.end_time or "") - to_timedelta(working_hour.start_time or "")).total_seconds() if slot_length >= operation_length: return frappe.throw(_("Operation {0} longer than any available working hours in workstation {1}, break down the operation into multiple operations").format(operation, workstation.name), NotInWorkingHoursError)
def is_within_operating_hours(workstation, operation, from_datetime, to_datetime): operation_length = time_diff_in_seconds(to_datetime, from_datetime) workstation = frappe.get_doc("Workstation", workstation) if not workstation.working_hours: return for working_hour in workstation.working_hours: if working_hour.start_time and working_hour.end_time: slot_length = (to_timedelta(working_hour.end_time or "") - to_timedelta(working_hour.start_time or "")).total_seconds() if slot_length >= operation_length: return frappe.throw(_("Operation {0} longer than any available working hours in workstation {1}, break down the operation into multiple operations").format(operation, workstation.name), NotInWorkingHoursError)
def validate_delivery_window(doc, method): from erpnext.stock.doctype.delivery_trip.delivery_trip import get_delivery_window if not frappe.db.get_single_value("Delivery Settings", "send_delivery_window_warning"): return if not (doc.get("delivery_start_time") and doc.get("delivery_end_time")): return if not doc.get("customer"): return delivery_window = get_delivery_window(customer=doc.get("customer")) delivery_start_time = delivery_window.delivery_start_time delivery_end_time = delivery_window.delivery_end_time if not (delivery_start_time and delivery_end_time): return if to_timedelta(doc.delivery_start_time) < to_timedelta(delivery_start_time) \ or to_timedelta(doc.delivery_end_time) > to_timedelta(delivery_end_time): if method == "validate": frappe.msgprint(_("The delivery window is set outside the customer's default timings")) elif method == "on_submit": # send an email notifying users that the document is outside the customer's delivery window role_profiles = ["Fulfillment Manager"] role_profile_users = frappe.get_all("User", filters={"role_profile_name": ["IN", role_profiles]}, fields=["email"]) role_profile_users = [user.email for user in role_profile_users] accounts_managers = get_users_with_role("Accounts Manager") system_managers = get_users_with_role("System Manager") recipients = list(set(role_profile_users + accounts_managers) - set(system_managers)) if not recipients: return # form the email subject = _("[Info] An order may be delivered outside a customer's preferred delivery window") message = _("""An order ({name}) has the following delivery window: {doc_start} - {doc_end}<br><br> While the default delivery window is {customer_start} - {customer_end}""".format( name=frappe.utils.get_link_to_form(doc.doctype, doc.name), doc_start=get_time(doc.delivery_start_time).strftime("%I:%M %p"), doc_end=get_time(doc.delivery_end_time).strftime("%I:%M %p"), customer_start=get_time(delivery_start_time).strftime("%I:%M %p"), customer_end=get_time(delivery_end_time).strftime("%I:%M %p"), )) frappe.sendmail(recipients=recipients, subject=subject, message=message)
def make_course_schedule_test_record(**args): args = frappe._dict(args) course_schedule = frappe.new_doc("Course Schedule") course_schedule.student_group = args.student_group or "_Test Student Group" course_schedule.course = args.course or "_Test Course" course_schedule.instructor = args.instructor or "_T-Instructor-00001" course_schedule.room = args.room or "RM0001" course_schedule.schedule_date = args.schedule_date or today() course_schedule.from_time = args.from_time or to_timedelta("01:00:00") course_schedule.to_time = args.to_time or course_schedule.from_time + datetime.timedelta( hours=1) if not args.do_not_save: if args.simulate: while True: try: course_schedule.save() break except OverlapError: course_schedule.from_time = course_schedule.from_time + datetime.timedelta( minutes=10) course_schedule.to_time = course_schedule.from_time + datetime.timedelta( hours=1) else: course_schedule.save() return course_schedule
def make_course_schedule_test_record(**args): args = frappe._dict(args) course_schedule = frappe.new_doc("Course Schedule") course_schedule.student_group = ( args.student_group or "Course-TC101-2014-2015 (_Test Academic Term)" ) course_schedule.course = args.course or "TC101" course_schedule.instructor = args.instructor or "_Test Instructor" course_schedule.room = args.room or frappe.get_all("Room")[0].name course_schedule.schedule_date = args.schedule_date or today() course_schedule.from_time = args.from_time or to_timedelta("01:00:00") course_schedule.to_time = args.to_time or course_schedule.from_time + datetime.timedelta(hours=1) if not args.do_not_save: if args.simulate: while True: try: course_schedule.save() break except OverlapError: course_schedule.from_time = course_schedule.from_time + datetime.timedelta(minutes=10) course_schedule.to_time = course_schedule.from_time + datetime.timedelta(hours=1) else: course_schedule.save() return course_schedule
def make_course_schedule_test_record(**args): args = frappe._dict(args) course_schedule = frappe.new_doc("Course Schedule") course_schedule.student_group = args.student_group or "Course-TC101-2014-2015 (_Test Academic Term)" course_schedule.course = args.course or "TC101" course_schedule.instructor = args.instructor or "_Test Instructor" course_schedule.room = args.room or frappe.get_all("Room")[0].name course_schedule.schedule_date = args.schedule_date or today() course_schedule.from_time = args.from_time or to_timedelta("01:00:00") course_schedule.to_time = args.to_time or course_schedule.from_time + datetime.timedelta(hours= 1) if not args.do_not_save: if args.simulate: while True: try: course_schedule.save() break except OverlapError: course_schedule.from_time = course_schedule.from_time + datetime.timedelta(minutes=10) course_schedule.to_time = course_schedule.from_time + datetime.timedelta(hours= 1) else: course_schedule.save() return course_schedule
def make_course_schedule_test_record(**args): args = frappe._dict(args) course_schedule = frappe.new_doc("Course Schedule") course_schedule.student_group = args.student_group or "_Test Student Group" course_schedule.course = args.course or "_Test Course" course_schedule.instructor = args.instructor or "_T-Instructor-00001" course_schedule.room = args.room or "RM0001" course_schedule.schedule_date = args.schedule_date or today() course_schedule.from_time = args.from_time or to_timedelta("01:00:00") course_schedule.to_time = args.to_time or course_schedule.from_time + datetime.timedelta(hours= 1) if not args.do_not_save: if args.simulate: while True: try: course_schedule.save() break except OverlapError: course_schedule.from_time = course_schedule.from_time + datetime.timedelta(minutes=10) course_schedule.to_time = course_schedule.from_time + datetime.timedelta(hours= 1) else: course_schedule.save() return course_schedule
def cast(self, val, df): if df.fieldtype in ("Currency", "Float", "Percent"): val = flt(val) elif df.fieldtype in ("Int", "Check"): val = cint(val) elif df.fieldtype in ( "Data", "Text", "Small Text", "Long Text", "Text Editor", "Select", "Link", "Dynamic Link", ): val = cstr(val) elif df.fieldtype == "Date": val = getdate(val) elif df.fieldtype == "Datetime": val = get_datetime(val) elif df.fieldtype == "Time": val = to_timedelta(val) return val
def create_nursing_task(doc, nursing_task): hc_nursing_task = frappe.new_doc("Healthcare Nursing Task") hc_nursing_task.patient = doc.patient hc_nursing_task.practitioner = doc.practitioner hc_nursing_task.task = nursing_task.check_list hc_nursing_task.service_unit = doc.service_unit hc_nursing_task.medical_department = doc.medical_department hc_nursing_task.task_order = nursing_task.task hc_nursing_task.reference_doctype = doc.doctype hc_nursing_task.reference_docname = doc.name hc_nursing_task.date = doc.start_date if doc.start_time and nursing_task.expected_time and nursing_task.expected_time > 0: if nursing_task.task == "After": hc_nursing_task.time = to_timedelta(doc.start_time) + datetime.timedelta(seconds=nursing_task.expected_time*60) elif nursing_task.task == "Before": hc_nursing_task.time = to_timedelta(doc.start_time) - datetime.timedelta(seconds=nursing_task.expected_time*60) hc_nursing_task.save(ignore_permissions=True)
def create_pre_post_document(doc): if doc.nursing_tasks: for nursing_task in doc.nursing_tasks: if not nursing_task.nursing_task_reference: create_nursing_task(doc, nursing_task) if doc.investigations: for investigation in doc.investigations: if not investigation.lab_test_reference: lab_test = create_lab_test_doc(True, doc.practitioner, frappe.get_doc("Patient", doc.patient), frappe.get_doc("Lab Test Template", investigation.lab_test)) lab_test.reference_dt = doc.doctype lab_test.reference_dn = doc.name lab_test.expected_result_date = doc.start_date if doc.start_time and investigation.expected_time and investigation.expected_time > 0: if investigation.task == "After": lab_test.expected_result_time = to_timedelta(doc.start_time) + datetime.timedelta(seconds=investigation.expected_time*60) elif investigation.task == "Before": lab_test.expected_result_time = to_timedelta(doc.start_time) - datetime.timedelta(seconds=investigation.expected_time*60) lab_test.save(ignore_permissions = True)
def check_support_and_resolution(self): week = get_weekdays() support_days = [] for support_and_resolution in self.support_and_resolution: support_days.append(support_and_resolution.workday) support_and_resolution.idx = week.index( support_and_resolution.workday) + 1 if to_timedelta(support_and_resolution.start_time) >= to_timedelta( support_and_resolution.end_time): frappe.throw( _("Start Time can't be greater than or equal to End Time for {0}." ).format(support_and_resolution.workday)) # Check for repeated workday if not len(set(support_days)) == len(support_days): repeated_days = get_repeated(support_days) frappe.throw( _("Workday {0} has been repeated.").format(repeated_days))
def create_nursing_task(doc, nursing_task): hc_nursing_task = frappe.new_doc("Healthcare Nursing Task") hc_nursing_task.patient = doc.patient hc_nursing_task.practitioner = doc.practitioner hc_nursing_task.task = nursing_task.check_list hc_nursing_task.service_unit = doc.service_unit hc_nursing_task.medical_department = doc.medical_department hc_nursing_task.task_order = nursing_task.task hc_nursing_task.reference_doctype = doc.doctype hc_nursing_task.reference_docname = doc.name hc_nursing_task.date = doc.start_date if doc.start_time and nursing_task.expected_time and nursing_task.expected_time > 0: if nursing_task.task == "After": hc_nursing_task.time = to_timedelta( doc.start_time) + datetime.timedelta( seconds=nursing_task.expected_time * 60) elif nursing_task.task == "Before": hc_nursing_task.time = to_timedelta( doc.start_time) - datetime.timedelta( seconds=nursing_task.expected_time * 60) hc_nursing_task.save(ignore_permissions=True)
def log_response(docname, response=None): """ update the response for the request """ res = json.loads(response) log = frappe.get_doc("API Log", docname) log.response_time = nowtime() log.response_date = nowdate() log.request_status = "Success" if res.get("code") == 200 else "Failed" log.response = json.dumps(res, indent=2) log.execution_time = "{0}".format(to_timedelta(log.response_time) - log.request_time) log.save(ignore_permissions=True) frappe.db.commit()
def cast(self, val, df): if df.fieldtype in ("Currency", "Float", "Percent"): val = flt(val) elif df.fieldtype in ("Int", "Check"): val = cint(val) elif df.fieldtype in ("Data", "Text", "Small Text", "Long Text", "Text Editor", "Select", "Link", "Dynamic Link"): val = cstr(val) elif df.fieldtype == "Date": val = getdate(val) elif df.fieldtype == "Datetime": val = get_datetime(val) elif df.fieldtype == "Time": val = to_timedelta(val) return val
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 attendance_times(self): from frappe.utils import to_timedelta d = datetime.datetime.strptime(self.attendance_date, '%Y-%m-%d') shift = frappe.db.get_value("Employee", self.employee, "shift_type") if frappe.db.exists("Shift Type", {"name": shift}) and self.status == "Present": self.total_hours = to_timedelta(self.end_time) - to_timedelta(self.start_time) shift_type = frappe.get_doc("Shift Type", {"name": shift}) remaining_minutes = (to_timedelta(frappe.db.sql("""select (sum(TIME_TO_SEC(late))) as lates from `tabAttendance` where employee = %s and month(attendance_date) = %s and over1 = "-120" and docstatus != 2 """ , [self.employee, d.month])[0][0]) ) if not remaining_minutes: remaining_minutes = 0.0 self.over1 = "N" else: remaining_minutes = remaining_minutes /60 self.remaining_minutes = 0.0 if to_timedelta(self.start_time) > to_timedelta(shift_type.start_time) and \ (to_timedelta(self.start_time) - to_timedelta(shift_type.start_time)) > to_timedelta(shift_type.late_attendance): self.late = to_timedelta(self.start_time) - to_timedelta(shift_type.start_time) self.over1 = "+15" elif to_timedelta(self.start_time) > to_timedelta(shift_type.start_time) and \ (to_timedelta(self.start_time) - to_timedelta(shift_type.start_time)) <= to_timedelta(shift_type.late_attendance) \ and remaining_minutes == to_timedelta(shift_type.total_allowance_minutes_on_month): self.late = to_timedelta(self.start_time) - to_timedelta(shift_type.start_time) self.over1 = "N" self.remaining_minutes = remaining_minutes elif to_timedelta(self.start_time) > to_timedelta(shift_type.start_time) and \ (to_timedelta(self.start_time) - to_timedelta(shift_type.start_time)) <= to_timedelta(shift_type.late_attendance) \ and remaining_minutes < to_timedelta(shift_type.total_allowance_minutes_on_month): self.late = to_timedelta(self.start_time) - to_timedelta(shift_type.start_time) self.over1 = "-120" self.remaining_minutes = remaining_minutes elif to_timedelta(self.start_time) > to_timedelta(shift_type.start_time) and \ (to_timedelta(self.start_time) - to_timedelta(shift_type.start_time)) <= to_timedelta(shift_type.late_attendance) \ and remaining_minutes > to_timedelta(shift_type.total_allowance_minutes_on_month): self.late = to_timedelta(self.start_time) - to_timedelta(shift_type.start_time) self.over1 = "+120" else: self.late = None self.over1 = "N" if to_timedelta(shift_type.end_time) > to_timedelta(self.end_time): self.early = to_timedelta(shift_type.end_time) - to_timedelta(self.end_time) else: self.early = None if to_timedelta(self.end_time) > to_timedelta(shift_type.end_time): self.extra_hours = to_timedelta(self.end_time) - to_timedelta(shift_type.end_time) else: self.extra_hours = None else: self.late = None self.early = None self.extra_hours = None if not self.status == "Present": self.start_time = None self.end_time = None self.total_hours = None if not frappe.db.exists("Shift Type", {"name": shift}) and self.status == "Present": self.total_hours = to_timedelta(self.end_time) - to_timedelta(self.start_time)