Esempio n. 1
0
    def validate_if_attendance_not_applicable(self, attendance_date):
        # Check if attendance_date is a Holiday
        if is_holiday(self.employee, attendance_date):
            frappe.msgprint(
                _("Attendance not submitted for {0} as it is a Holiday."
                  ).format(attendance_date),
                alert=1)
            return True

        # Check if employee on Leave
        leave_record = frappe.db.sql(
            """select half_day from `tabLeave Application`
			where employee = %s and %s between from_date and to_date
			and docstatus = 1""",
            (self.employee, attendance_date),
            as_dict=True,
        )
        if leave_record:
            frappe.msgprint(
                _("Attendance not submitted for {0} as {1} on leave.").format(
                    attendance_date, self.employee),
                alert=1,
            )
            return True

        return False
Esempio n. 2
0
def check_employee_wise_availability(date, practitioner_doc):
    employee = None
    if practitioner_doc.employee:
        employee = practitioner_doc.employee
    elif practitioner_doc.user_id:
        employee = frappe.db.get_value('Employee',
                                       {'user_id': practitioner_doc.user_id},
                                       'name')

    if employee:
        # check holiday
        if is_holiday(employee, date):
            frappe.throw(_('{0} is a holiday'.format(date)),
                         title=_('Not Available'))

        # check leave status
        leave_record = frappe.db.sql(
            """select half_day from `tabLeave Application`
			where employee = %s and %s between from_date and to_date
			and docstatus = 1""", (employee, date),
            as_dict=True)
        if leave_record:
            if leave_record[0].half_day:
                frappe.throw(_('{0} is on a Half day Leave on {1}').format(
                    practitioner_doc.name, date),
                             title=_('Not Available'))
            else:
                frappe.throw(_('{0} is on Leave on {1}').format(
                    practitioner_doc.name, date),
                             title=_('Not Available'))
Esempio n. 3
0
    def test_is_holiday(self):
        from erpnext.hr.doctype.employee.employee import is_holiday

        self.assertTrue(is_holiday(self.test_employee.name))
        self.assertTrue(
            is_holiday(self.test_employee.name,
                       date=self.test_holiday_dates[1]))
        self.assertFalse(
            is_holiday(self.test_employee.name,
                       date=getdate() - timedelta(days=1)))

        # Test weekly_off holidays
        self.assertTrue(
            is_holiday(self.test_employee.name,
                       date=self.test_holiday_dates[2]))
        self.assertFalse(
            is_holiday(self.test_employee.name,
                       date=self.test_holiday_dates[2],
                       only_non_weekly=True))

        # Test with descriptions
        has_holiday, descriptions = is_holiday(self.test_employee.name,
                                               with_description=True)
        self.assertTrue(has_holiday)
        self.assertTrue('test holiday1' in descriptions)
def get_employee_emails(company, only_working=True):
	'''Returns list of Employee user ids for the given company who are working today

	:param company: Company `name`'''
	employee_list = frappe.get_all('Employee', fields=['name', 'user_id'],
		filters={'status': 'Active', 'company': company})

	out = []
	for e in employee_list:
		if e.user_id:
			if only_working and is_holiday(e.name):
				# don't add if holiday
				continue
			out.append(e.user_id)

	return out
Esempio n. 5
0
def get_employee_emails(company, only_working=True):
	'''Returns list of Employee user ids for the given company who are working today

	:param company: Company `name`'''
	employee_list = frappe.get_all('Employee', fields=['name', 'user_id'],
		filters={'status': 'Active', 'company': company})

	out = []
	for e in employee_list:
		if e.user_id:
			if only_working and is_holiday(e.name):
				# don't add if holiday
				continue
			out.append(e.user_id)

	return out
Esempio n. 6
0
def get_availability_data(date, physician):
	"""
	Get availability data of 'physician' on 'date'
	:param date: Date to check in schedule
	:param physician: Name of the physician
	:return: dict containing a list of available slots, list of appointments and time of appointments
	"""

	date = getdate(date)
	weekday = date.strftime("%A")

	available_slots = []
	slot_details = []
	physician_schedule = None

	employee = None

	physician_obj = frappe.get_doc("Physician", physician)

	# Get Physician employee relation
	if physician_obj.employee:
		employee = physician_obj.employee
	elif physician_obj.user_id:
		if frappe.db.exists({
			"doctype": "Employee",
			"user_id": physician_obj.user_id
			}):
			employee = frappe.get_doc("Employee", {"user_id": physician_obj.user_id}).name

	if employee:
		# Check if it is Holiday
		if is_holiday(employee, date):
			frappe.throw(_("{0} is a company holiday".format(date)))

		# Check if He/She on Leave
		leave_record = frappe.db.sql("""select half_day from `tabLeave Application`
			where employee = %s and %s between from_date and to_date
			and docstatus = 1""", (employee, date), as_dict=True)
		if leave_record:
			if leave_record[0].half_day:
				frappe.throw(_("Dr {0} on Half day Leave on {1}").format(physician, date))
			else:
				frappe.throw(_("Dr {0} on Leave on {1}").format(physician, date))

	# get physicians schedule
	if physician_obj.physician_schedules:
		for schedule in physician_obj.physician_schedules:
			if schedule.schedule:
				physician_schedule = frappe.get_doc("Physician Schedule", schedule.schedule)
			else:
				frappe.throw(_("Dr {0} does not have a Physician Schedule. Add it in Physician master".format(physician)))

			if physician_schedule:
				available_slots = []
				for t in physician_schedule.time_slots:
					if weekday == t.day:
						available_slots.append(t)

				if available_slots:
					appointments = []
					
					if schedule.service_unit:
						slot_name  = schedule.schedule+" - "+schedule.service_unit
						allow_overlap = frappe.get_value('Patient Service Unit', schedule.service_unit, 'overlap_appointments')
						if allow_overlap:
							# fetch all appointments to physician by service unit
							appointments = frappe.get_all(
								"Patient Appointment",
								filters={"physician": physician, "service_unit": schedule.service_unit, "appointment_date": date, "status": ["not in",["Cancelled"]]},
								fields=["name", "appointment_time", "duration", "status"])
						else:
							# fetch all appointments to service unit
							appointments = frappe.get_all(
								"Patient Appointment",
								filters={"service_unit": schedule.service_unit, "appointment_date": date, "status": ["not in",["Cancelled"]]},
								fields=["name", "appointment_time", "duration", "status"])
					else:
						slot_name = schedule.schedule
						# fetch all appointments to physician without service unit
						appointments = frappe.get_all(
							"Patient Appointment",
							filters={"physician": physician, "service_unit": '', "appointment_date": date, "status": ["not in",["Cancelled"]]},
							fields=["name", "appointment_time", "duration", "status"])

					slot_details.append({"slot_name":slot_name, "service_unit":schedule.service_unit,
						"avail_slot":available_slots, 'appointments': appointments})

	else:
		frappe.throw(_("Dr {0} does not have a Physician Schedule. Add it in Physician master".format(physician)))

	if not available_slots and not slot_details:
		# TODO: return available slots in nearby dates
		frappe.throw(_("Physician not available on {0}").format(weekday))

	return {
		"slot_details": slot_details
	}
Esempio n. 7
0
def attendence_proccessing(employee_list,
                           status,
                           start_date,
                           leave_type=None,
                           company=None,
                           end_date=None):
    validate_dates(start_date, end_date)
    employee_list = json.loads(employee_list)

    days_types = {
        "Present": "P",
        "Absent": "A",
        "Half Day": "HD",
        "On Leave": "L",
        "None": "",
        "Unallocated": "<b>U</b>"
    }
    dict_days = frappe._dict()

    start_date, end_date = getdate(start_date), getdate(end_date)
    leave_type = ""

    for single_date in daterange(start_date, end_date):
        curr_single_date = getdate(single_date)
        # is_holiday = False
        for employee in employee_list:
            employee["date"] = curr_single_date
            attendance_log = get_emp_log(curr_single_date,
                                         employee["employee"])
            # frappe.msgprint(str(attendance_log))
            if attendance_log == []:
                is_leave_mission_rest = check_leave_mission_rest(
                    employee["employee"], curr_single_date)
                if (not is_leave_mission_rest) and (not is_holiday(
                        employee["employee"], curr_single_date)):
                    add_attendance(employee,
                                   "Absent",
                                   curr_single_date,
                                   attend_time="",
                                   leave_time="")
            else:
                # Check if Emp is Assigned to Period and return Period data
                emp_data_Dic = check_assigned_period(employee['employee'],
                                                     curr_single_date)

                if emp_data_Dic == []:
                    dict_days[curr_single_date] = days_types[
                        "Unallocated"]  # =======> to store days without period
                elif (emp_data_Dic["attendance_type"] == "Shift"):
                    attend_time = None  # اول معاد حضور
                    leave_time = ""  # معاد الانصراف
                    attend_notes = ""
                    late_minutes = 0.0
                    has_signed_after_permission = False
                    after_period_end_time = False
                    atendance_time_margin = frappe.db.get_single_value(
                        "Attendances Settings",
                        "attendance_time_margin",
                        cache=False)
                    max_limit_for_attend = frappe.db.get_single_value(
                        "Attendances Settings",
                        "max_limit_for_attendance",
                        cache=False)

                    time_margin_after_leave_time = frappe.db.get_single_value(
                        "Attendances Settings",
                        "leave_time_margin",
                        cache=False)

                    for item in attendance_log:
                        #---------------------------------------Attend Variables----------------------------------------------
                        max_time_after_attend = emp_data_Dic[
                            "start_time"] + timedelta(minutes=int(
                                emp_data_Dic["attendance_permissibility"]))
                        max_time_before_attend = emp_data_Dic[
                            "start_time"] - timedelta(
                                minutes=int(atendance_time_margin))
                        max_limit_for_attendance = emp_data_Dic[
                            "start_time"] + timedelta(
                                minutes=int(max_limit_for_attend))

                        #---------------------------------------Leave Variables----------------------------------------------
                        start_time_to_leave = emp_data_Dic[
                            "end_time"] - timedelta(minutes=int(
                                emp_data_Dic["leave_permissibility"]))
                        max_time_to_leave = emp_data_Dic[
                            "end_time"] + timedelta(
                                minutes=int(time_margin_after_leave_time))
                        #-----------------------------------------------------------------------------------------------------

                        item_time_stamp = datetime.strptime(
                            item["timestamp"], "%H:%M:%S")
                        item_time_stamp = timedelta(
                            hours=item_time_stamp.hour,
                            minutes=item_time_stamp.minute,
                            seconds=item_time_stamp.second)

                        # حضور قبل الموعد
                        # During Attendance Time Margin (Before Period Start Time)
                        if (emp_data_Dic["start_time"] > item_time_stamp >=
                                max_time_before_attend):
                            attend_time = item_time_stamp
                            attend_notes = "حضور قبل الموعد"

                        # حضور قبل الموعد وقبل فنرة الحضور المبكر
                        elif (emp_data_Dic["start_time"] > item_time_stamp <
                              max_time_before_attend):
                            attend_time = ""
                            attend_notes = "حضور مبكر"

                        # حضور في الموعد أو خلال فترة السماحية
                        elif ((emp_data_Dic["start_time"] <= item_time_stamp <=
                               max_time_after_attend)):
                            attend_time = item_time_stamp  # حضور اول معاد
                            attend_notes = "حضور يومى"

                        #حضور بعد وقت الفترة وبعد وقت السماحية
                        elif (item_time_stamp > max_time_after_attend):
                            if check_permission(
                                    employee['employee'],
                                    curr_single_date,
                                    late_attend=True) and (
                                        not has_signed_after_permission
                                    ):  # إذن الحضور
                                attend_time = item_time_stamp  # إذن حضور
                                attend_notes = "إذن حضور"
                                has_signed_after_permission = True

                            elif (item_time_stamp < max_limit_for_attendance):
                                attend_time = item_time_stamp  # حضور مع التاخير
                                attend_notes = " حضور مع التأخير"
                                late_seconds = (
                                    attend_time -
                                    max_time_after_attend).total_seconds()
                                late_minutes = late_seconds / 60  #تأخير عن ميعاد الحضور
                        #-------------------------------------------Leave Conditions-------------------------------------------------
                            elif (item_time_stamp < start_time_to_leave):
                                if check_permission(employee['employee'],
                                                    curr_single_date,
                                                    late_attend=False):
                                    attend_notes += "- اذن انصراف مبكر "
                                else:
                                    attend_notes += "-  إنصراف قبل الموعد "
                                leave_time = item_time_stamp

                            elif (start_time_to_leave <= item_time_stamp <=
                                  max_time_to_leave):
                                leave_time = item_time_stamp
                                attend_notes += "-  إنصراف يومى "

                            elif (item_time_stamp > max_time_to_leave):
                                attend_notes += "-  إنصراف بعد الموعد "
                                leave_time = ""
                                after_period_end_time = True

                    if attend_time and (not leave_time):
                        if not after_period_end_time:
                            attend_notes += "- عدم توقيع انصراف"

                    add_attendance(employee, status, curr_single_date,
                                   attend_time, leave_time, late_minutes,
                                   attend_notes, leave_type)
                elif (emp_data_Dic["attendance_type"]
                      in ("Open Day", "Flexible Hours")):
                    attend_time = None  # اول معاد حضور
                    leave_time = ""  # معاد الانصراف
                    attend_notes = ""
                    current_timestamp_to_handle = ""
                    total_hours_per_day = "00:00:00"
                    for item in attendance_log:
                        item_time_stamp = datetime.strptime(
                            item["timestamp"], "%H:%M:%S")
                        item_time_stamp = timedelta(
                            hours=item_time_stamp.hour,
                            minutes=item_time_stamp.minute,
                            seconds=item_time_stamp.second)

                        if attend_time == None:
                            attend_time = item_time_stamp
                            current_timestamp_to_handle = item_time_stamp
                            status = "Present"
                            attend_notes = "حضور يومى"

                        elif (current_timestamp_to_handle == ""):
                            current_timestamp_to_handle = item_time_stamp

                        elif (current_timestamp_to_handle != "" and
                              (item_time_stamp - current_timestamp_to_handle) >
                              timedelta(minutes=5)):
                            temp = (item_time_stamp -
                                    current_timestamp_to_handle)
                            temp = str(datetime.strptime(
                                str(temp), "%H:%M:%S")).split(' ')[1]

                            total_hours_per_day = \
                            timedelta(hours=int(str(temp).split(':')[0]), minutes=int(str(temp).split(':')[1]), seconds=int(str(temp).split(':')[1])) + \
                            timedelta(hours=int(str(total_hours_per_day).split(':')[0]), minutes=int(str(total_hours_per_day).split(':')[1]), seconds=int(str(total_hours_per_day).split(':')[2]))
                            current_timestamp_to_handle = ""

                        leave_time = item_time_stamp

                    add_attendance(employee,
                                   status,
                                   curr_single_date,
                                   attend_time,
                                   leave_time,
                                   0.0,
                                   attend_notes,
                                   leave_type,
                                   daily_hours=str(total_hours_per_day))
Esempio n. 8
0
def get_availability_data(date, practitioner):
	"""
	Get availability data of 'practitioner' on 'date'
	:param date: Date to check in schedule
	:param practitioner: Name of the practitioner
	:return: dict containing a list of available slots, list of appointments and time of appointments
	"""

	date = getdate(date)
	weekday = date.strftime("%A")

	available_slots = []
	slot_details = []
	practitioner_schedule = None

	employee = None

	practitioner_obj = frappe.get_doc("Healthcare Practitioner", practitioner)

	# Get practitioner employee relation
	if practitioner_obj.employee:
		employee = practitioner_obj.employee
	elif practitioner_obj.user_id:
		if frappe.db.exists({
			"doctype": "Employee",
			"user_id": practitioner_obj.user_id
			}):
			employee = frappe.get_doc("Employee", {"user_id": practitioner_obj.user_id}).name

	if employee:
		# Check if it is Holiday
		if is_holiday(employee, date):
			frappe.throw(_("{0} is a company holiday".format(date)))

		# Check if He/She on Leave
		leave_record = frappe.db.sql("""select half_day from `tabLeave Application`
			where employee = %s and %s between from_date and to_date
			and docstatus = 1""", (employee, date), as_dict=True)
		if leave_record:
			if leave_record[0].half_day:
				frappe.throw(_("{0} on Half day Leave on {1}").format(practitioner, date))
			else:
				frappe.throw(_("{0} on Leave on {1}").format(practitioner, date))

	# get practitioners schedule
	if practitioner_obj.practitioner_schedules:
		for schedule in practitioner_obj.practitioner_schedules:
			if schedule.schedule:
				practitioner_schedule = frappe.get_doc("Practitioner Schedule", schedule.schedule)
			else:
				frappe.throw(_("{0} does not have a Healthcare Practitioner Schedule. Add it in Healthcare Practitioner master".format(practitioner)))

			if practitioner_schedule:
				available_slots = []
				for t in practitioner_schedule.time_slots:
					if weekday == t.day:
						available_slots.append(t)

				if available_slots:
					appointments = []

					if schedule.service_unit:
						slot_name  = schedule.schedule+" - "+schedule.service_unit
						allow_overlap = frappe.get_value('Healthcare Service Unit', schedule.service_unit, 'overlap_appointments')
						if allow_overlap:
							# fetch all appointments to practitioner by service unit
							appointments = frappe.get_all(
								"Patient Appointment",
								filters={"practitioner": practitioner, "service_unit": schedule.service_unit, "appointment_date": date, "status": ["not in",["Cancelled"]]},
								fields=["name", "appointment_time", "duration", "status"])
						else:
							# fetch all appointments to service unit
							appointments = frappe.get_all(
								"Patient Appointment",
								filters={"service_unit": schedule.service_unit, "appointment_date": date, "status": ["not in",["Cancelled"]]},
								fields=["name", "appointment_time", "duration", "status"])
					else:
						slot_name = schedule.schedule
						# fetch all appointments to practitioner without service unit
						appointments = frappe.get_all(
							"Patient Appointment",
							filters={"practitioner": practitioner, "service_unit": '', "appointment_date": date, "status": ["not in",["Cancelled"]]},
							fields=["name", "appointment_time", "duration", "status"])

					slot_details.append({"slot_name":slot_name, "service_unit":schedule.service_unit,
						"avail_slot":available_slots, 'appointments': appointments})

	else:
		frappe.throw(_("{0} does not have a Healthcare Practitioner Schedule. Add it in Healthcare Practitioner master".format(practitioner)))

	if not available_slots and not slot_details:
		# TODO: return available slots in nearby dates
		frappe.throw(_("Healthcare Practitioner not available on {0}").format(weekday))

	return {
		"slot_details": slot_details
	}
def get_availability_data(date, physician):
    """
	Get availability data of 'physician' on 'date'
	:param date: Date to check in schedule
	:param physician: Name of the physician
	:return: dict containing a list of available slots, list of appointments and time of appointments
	"""

    date = getdate(date)
    weekday = date.strftime("%A")

    available_slots = []
    physician_schedule_name = None
    physician_schedule = None
    time_per_appointment = None
    employee = None

    physician_obj = frappe.get_doc("Physician", physician)

    # Get Physician employee relation
    if physician_obj.employee:
        employee = physician_obj.employee
    elif physician_obj.user_id:
        if frappe.db.exists({
                "doctype": "Employee",
                "user_id": physician_obj.user_id
        }):
            employee = frappe.get_doc("Employee", {
                "user_id": physician_obj.user_id
            }).name

    if employee:
        # Check if it is Holiday
        if is_holiday(employee, date):
            frappe.throw(_("{0} is a company holiday".format(date)))

        # Check if He/She on Leave
        leave_record = frappe.db.sql(
            """select half_day from `tabLeave Application`
			where employee = %s and %s between from_date and to_date and status = 'Approved'
			and docstatus = 1""", (employee, date),
            as_dict=True)
        if leave_record:
            if leave_record[0].half_day:
                frappe.throw(
                    _("Dr {0} on Half day Leave on {1}").format(
                        physician, date))
            else:
                frappe.throw(
                    _("Dr {0} on Leave on {1}").format(physician, date))

    # get physicians schedule
    physician_schedule_name = frappe.db.get_value("Physician", physician,
                                                  "physician_schedule")
    if physician_schedule_name:
        physician_schedule = frappe.get_doc("Physician Schedule",
                                            physician_schedule_name)
        time_per_appointment = frappe.db.get_value("Physician", physician,
                                                   "time_per_appointment")
    else:
        frappe.throw(
            _("Dr {0} does not have a Physician Schedule. Add it in Physician master"
              .format(physician)))

    if physician_schedule:
        for t in physician_schedule.time_slots:
            if weekday == t.day:
                available_slots.append(t)

    # `time_per_appointment` should never be None since validation in `Patient` is supposed to prevent
    # that. However, it isn't impossible so we'll prepare for that.
    if not time_per_appointment:
        frappe.throw(
            _('"Time Per Appointment" hasn"t been set for Dr {0}. Add it in Physician master.'
              ).format(physician))

    # if physician not available return
    if not available_slots:
        # TODO: return available slots in nearby dates
        frappe.throw(_("Physician not available on {0}").format(weekday))

    # if physician on leave return

    # if holiday return
    # if is_holiday(weekday):

    # get appointments on that day for physician
    appointments = frappe.get_all(
        "Patient Appointment",
        filters={
            "physician": physician,
            "appointment_date": date
        },
        fields=["name", "appointment_time", "duration", "status"])

    return {
        "available_slots": available_slots,
        "appointments": appointments,
        "time_per_appointment": time_per_appointment
    }
Esempio n. 10
0
def get_availability_data(date, practitioner):
	"""
	Get availability data of 'practitioner' on 'date'
	:param date: Date to check in schedule
	:param practitioner: Name of the practitioner
	:return: dict containing a list of available slots, list of appointments and time of appointments
	"""

	date = getdate(date)
	weekday = date.strftime("%A")

	available_slots = []
	slot_details = []
	practitioner_schedule = None

	add_events = []
	remove_events = []

	employee = None

	practitioner_obj = frappe.get_doc("Healthcare Practitioner", practitioner)

	# Get practitioner employee relation
	if practitioner_obj.employee:
		employee = practitioner_obj.employee
	elif practitioner_obj.user_id:
		if frappe.db.exists({
			"doctype": "Employee",
			"user_id": practitioner_obj.user_id
			}):
			employee = frappe.get_doc("Employee", {"user_id": practitioner_obj.user_id}).name

	if employee:
		# Check if it is Holiday
		if is_holiday(employee, date):
			frappe.throw(_("{0} is a company holiday".format(date)))

		# Check if He/She on Leave
		leave_record = frappe.db.sql("""select half_day from `tabLeave Application`
			where employee = %s and %s between from_date and to_date
			and docstatus = 1""", (employee, date), as_dict=True)
		if leave_record:
			if leave_record[0].half_day:
				frappe.throw(_("{0} on Half day Leave on {1}").format(practitioner, date))
			else:
				frappe.throw(_("{0} on Leave on {1}").format(practitioner, date))

	# Remove events by repeat_on
	def remove_events_by_repeat_on(events_list):
		weekdays = ["monday", "tuesday", "wednesday", "thursday", "friday", "saturday", "sunday"]
		if events_list:
			i = 0
			for event in events_list:
				if event.repeat_this_event:
					if event.repeat_on == "Every Day":
						if event[weekdays[getdate(date).weekday()]]:
							add_events.append(event.copy())
						remove_events.append(event.copy())

					if event.repeat_on=="Every Week":
						if getdate(event.from_date).weekday() == getdate(date).weekday():
							add_events.append(event.copy())
						remove_events.append(event.copy())

					if event.repeat_on=="Every Month":
						if getdate(event.from_date).day == getdate(date).day:
							add_events.append(event.copy())
						remove_events.append(event.copy())

					if event.repeat_on=="Every Year":
						if getdate(event.from_date).strftime("%j") == getdate(date).strftime("%j"):
							add_events.append(event.copy())
						remove_events.append(event.copy())

	# Absent events
	absent_events = frappe.db.sql("""
		select
			name, event, from_time, to_time, from_date, to_date, duration, service_unit, service_unit, repeat_this_event, repeat_on, repeat_till,
			monday, tuesday, wednesday, thursday, friday, saturday, sunday
		from
			`tabPractitioner Event`
		where
			practitioner = %(practitioner)s and present != 1 and
			(
				(repeat_this_event = 1 and (from_date<=%(date)s and ifnull(repeat_till, "3000-01-01")>=%(date)s))
				or
				(repeat_this_event != 1 and (from_date<=%(date)s and to_date>=%(date)s))
			)
	""".format(),{"practitioner": practitioner, "date": getdate(date)}, as_dict=True)

	if absent_events:
		remove_events = []
		add_events = []
		remove_events_by_repeat_on(absent_events)
		for e in remove_events:
			absent_events.remove(e)
		absent_events = absent_events + add_events

	# get practitioners schedule
	enabled_schedule = False
	if practitioner_obj.practitioner_schedules:
		for schedule in practitioner_obj.practitioner_schedules:
			practitioner_schedule = None
			if schedule.schedule:
				if frappe.db.exists(
					"Practitioner Schedule",
					{
						"name": schedule.schedule,
						"disabled": ['!=', 1]
					}
				):
					practitioner_schedule = frappe.get_doc('Practitioner Schedule', schedule.schedule)
					enabled_schedule = True

			if practitioner_schedule:
				available_slots = []
				for t in practitioner_schedule.time_slots:
					if weekday == t.day:
						available_slots.append(t)

				if available_slots:
					appointments = []

					if schedule.service_unit:
						slot_name  = schedule.schedule+" - "+schedule.service_unit
						allow_overlap = frappe.get_value('Healthcare Service Unit', schedule.service_unit, 'overlap_appointments')
						if allow_overlap:
							# fetch all appointments to practitioner by service unit
							appointments = frappe.get_all(
								"Patient Appointment",
								filters={"practitioner": practitioner, "service_unit": schedule.service_unit, "appointment_date": date, "status": ["not in",["Cancelled"]]},
								fields=["name", "appointment_time", "duration", "status"],
								order_by= "appointment_date, appointment_time")
						else:
							# fetch all appointments to service unit
							appointments = frappe.get_all(
								"Patient Appointment",
								filters={"service_unit": schedule.service_unit, "appointment_date": date, "status": ["not in",["Cancelled"]]},
								fields=["name", "appointment_time", "duration", "status"],
								order_by= "appointment_date, appointment_time")
					else:
						slot_name = schedule.schedule
						# fetch all appointments to practitioner without service unit
						appointments = frappe.get_all(
							"Patient Appointment",
							filters={"practitioner": practitioner, "service_unit": '', "appointment_date": date, "status": ["not in",["Cancelled"]]},
							fields=["name", "appointment_time", "duration", "status"],
							order_by= "appointment_date, appointment_time")

					slot_details.append({"slot_name":slot_name, "service_unit":schedule.service_unit,
						"avail_slot":available_slots, 'appointments': appointments, 'absent_events': absent_events,
						'fixed_duration': schedule.always_use_slot_duration_as_appointment_duration, 'appointment_type': schedule.appointment_type})

	# Present events
	present_events = frappe.db.sql("""
		select
			name, event, from_time, to_time, from_date, to_date, duration, service_unit, repeat_this_event, repeat_on, repeat_till,
			monday, tuesday, wednesday, thursday, friday, saturday, sunday
		from
			`tabPractitioner Event`
		where
			practitioner = %(practitioner)s and present = 1 and
			(
				(repeat_this_event = 1 and (from_date<=%(date)s and ifnull(repeat_till, "3000-01-01")>=%(date)s))
				or
				(repeat_this_event != 1 and (from_date<=%(date)s and to_date>=%(date)s))
			)
	""".format(),{"practitioner":practitioner, "date":getdate(date)}, as_dict=True)

	present_events_details = []
	if present_events:
		remove_events = []
		add_events = []
		remove_events_by_repeat_on(present_events)
		for e in remove_events:
			present_events.remove(e)
		present_events = present_events + add_events

		for present_event in present_events:
			event_available_slots = []
			total_time_diff = time_diff_in_seconds(present_event.to_time, present_event.from_time)/60
			from_time = present_event.from_time
			slot_name = present_event.event
			appointments = []

			if present_event.service_unit:
				slot_name  = slot_name+" - "+present_event.service_unit
				allow_overlap = frappe.get_value('Healthcare Service Unit', present_event.service_unit, 'overlap_appointments')
				if allow_overlap:
					# fetch all appointments to practitioner by service unit
					appointments = frappe.get_all(
						"Patient Appointment",
						filters={"practitioner": practitioner, "service_unit": present_event.service_unit, "appointment_date": date, "status": ["not in",["Cancelled"]]},
						fields=["name", "appointment_time", "duration", "status"],
						order_by= "appointment_date, appointment_time")
				else:
					# fetch all appointments to service unit
					appointments = frappe.get_all(
						"Patient Appointment",
						filters={"service_unit": present_event.service_unit, "appointment_date": date, "status": ["not in",["Cancelled"]]},
						fields=["name", "appointment_time", "duration", "status"],
						order_by= "appointment_date, appointment_time")
			else:
				# fetch all appointments to practitioner without service unit
				appointments = frappe.get_all(
					"Patient Appointment",
					filters={"practitioner": practitioner, "service_unit": '', "appointment_date": date, "status": ["not in",["Cancelled"]]},
					fields=["name", "appointment_time", "duration", "status"],
					order_by= "appointment_date, appointment_time")

			for x in range(0, int(total_time_diff), present_event.duration):
				to_time = from_time + datetime.timedelta(seconds=present_event.duration*60)
				event_available_slots.append({'from_time': from_time, 'to_time': to_time})
				from_time = to_time
			present_events_details.append({'slot_name': slot_name, "service_unit":present_event.service_unit,
			'avail_slot': event_available_slots, 'appointments': appointments, 'absent_events': absent_events})
	else:
		if not practitioner_obj.practitioner_schedules:
			frappe.throw(_("{0} does not have a Healthcare Practitioner Schedule. Add it in Healthcare Practitioner master".format(practitioner)))
		elif not enabled_schedule:
			frappe.throw(_("{0} does not have an enabled Healthcare Practitioner Schedule.".format(practitioner)))
		elif not available_slots and not slot_details:
			frappe.throw(_("Healthcare Practitioner not available on {0}").format(weekday))

	return {
		"slot_details": slot_details,
		"present_events": present_events_details
	}