test: shift assignment creation
diff --git a/erpnext/hr/doctype/employee_checkin/test_employee_checkin.py b/erpnext/hr/doctype/employee_checkin/test_employee_checkin.py
index ed7877f..b0716be 100644
--- a/erpnext/hr/doctype/employee_checkin/test_employee_checkin.py
+++ b/erpnext/hr/doctype/employee_checkin/test_employee_checkin.py
@@ -23,6 +23,8 @@
 	mark_attendance_and_link_log,
 )
 from erpnext.hr.doctype.leave_application.test_leave_application import get_first_sunday
+from erpnext.hr.doctype.shift_assignment.test_shift_assignment import make_shift_assignment
+from erpnext.hr.doctype.shift_type.test_shift_type import setup_shift_type
 from erpnext.payroll.doctype.salary_slip.test_salary_slip import make_holiday_list
 
 
@@ -280,45 +282,3 @@
 		}
 	).insert()
 	return log
-
-
-def setup_shift_type(**args):
-	args = frappe._dict(args)
-	shift_type = frappe.new_doc("Shift Type")
-	shift_type.__newname = args.shift_type or "_Test Shift"
-	shift_type.start_time = args.start_time or "08:00:00"
-	shift_type.end_time = args.end_time or "12:00:00"
-	shift_type.holiday_list = args.holiday_list
-	shift_type.enable_auto_attendance = 1
-
-	shift_type.determine_check_in_and_check_out = (
-		args.determine_check_in_and_check_out
-		or "Alternating entries as IN and OUT during the same shift"
-	)
-	shift_type.working_hours_calculation_based_on = (
-		args.working_hours_calculation_based_on or "First Check-in and Last Check-out"
-	)
-	shift_type.begin_check_in_before_shift_start_time = (
-		args.begin_check_in_before_shift_start_time or 60
-	)
-	shift_type.allow_check_out_after_shift_end_time = args.allow_check_out_after_shift_end_time or 60
-
-	shift_type.save()
-
-	return shift_type
-
-
-def make_shift_assignment(shift_type, employee, start_date, end_date=None):
-	shift_assignment = frappe.get_doc(
-		{
-			"doctype": "Shift Assignment",
-			"shift_type": shift_type,
-			"company": "_Test Company",
-			"employee": employee,
-			"start_date": start_date,
-			"end_date": end_date,
-		}
-	).insert()
-	shift_assignment.submit()
-
-	return shift_assignment
diff --git a/erpnext/hr/doctype/shift_assignment/test_shift_assignment.py b/erpnext/hr/doctype/shift_assignment/test_shift_assignment.py
index 4a1ec29..8759870 100644
--- a/erpnext/hr/doctype/shift_assignment/test_shift_assignment.py
+++ b/erpnext/hr/doctype/shift_assignment/test_shift_assignment.py
@@ -4,16 +4,23 @@
 import unittest
 
 import frappe
-from frappe.utils import add_days, nowdate
+from frappe.tests.utils import FrappeTestCase
+from frappe.utils import add_days, getdate, nowdate
+
+from erpnext.hr.doctype.employee.test_employee import make_employee
+from erpnext.hr.doctype.shift_assignment.shift_assignment import OverlappingShiftError
+from erpnext.hr.doctype.shift_type.test_shift_type import setup_shift_type
 
 test_dependencies = ["Shift Type"]
 
 
-class TestShiftAssignment(unittest.TestCase):
+class TestShiftAssignment(FrappeTestCase):
 	def setUp(self):
-		frappe.db.sql("delete from `tabShift Assignment`")
+		frappe.db.delete("Shift Assignment")
+		frappe.db.delete("Shift Type")
 
 	def test_make_shift_assignment(self):
+		setup_shift_type(shift_type="Day Shift")
 		shift_assignment = frappe.get_doc(
 			{
 				"doctype": "Shift Assignment",
@@ -29,7 +36,7 @@
 
 	def test_overlapping_for_ongoing_shift(self):
 		# shift should be Ongoing if Only start_date is present and status = Active
-
+		setup_shift_type(shift_type="Day Shift")
 		shift_assignment_1 = frappe.get_doc(
 			{
 				"doctype": "Shift Assignment",
@@ -54,11 +61,11 @@
 			}
 		)
 
-		self.assertRaises(frappe.ValidationError, shift_assignment.save)
+		self.assertRaises(OverlappingShiftError, shift_assignment.save)
 
 	def test_overlapping_for_fixed_period_shift(self):
 		# shift should is for Fixed period if Only start_date and end_date both are present and status = Active
-
+		setup_shift_type(shift_type="Day Shift")
 		shift_assignment_1 = frappe.get_doc(
 			{
 				"doctype": "Shift Assignment",
@@ -85,4 +92,81 @@
 			}
 		)
 
-		self.assertRaises(frappe.ValidationError, shift_assignment_3.save)
+		self.assertRaises(OverlappingShiftError, shift_assignment_3.save)
+
+	def test_overlapping_for_a_fixed_period_shift_and_ongoing_shift(self):
+		employee = make_employee("test_shift_assignment@example.com", company="_Test Company")
+
+		# shift setup for 8-12
+		shift_type = setup_shift_type(shift_type="Shift 1", start_time="08:00:00", end_time="12:00:00")
+		date = getdate()
+		# shift with end date
+		make_shift_assignment(shift_type.name, employee, date, add_days(date, 30))
+
+		# shift setup for 13-15
+		shift_type = setup_shift_type(shift_type="Shift 2", start_time="11:00:00", end_time="15:00:00")
+		date = getdate()
+
+		# shift assignment without end date
+		shift2 = frappe.get_doc(
+			{
+				"doctype": "Shift Assignment",
+				"shift_type": shift_type.name,
+				"company": "_Test Company",
+				"employee": employee,
+				"start_date": date,
+			}
+		)
+		self.assertRaises(OverlappingShiftError, shift2.insert)
+
+	def test_overlap_validation_for_shifts_on_same_day_with_overlapping_timeslots(self):
+		employee = make_employee("test_shift_assignment@example.com", company="_Test Company")
+
+		# shift setup for 8-12
+		shift_type = setup_shift_type(shift_type="Shift 1", start_time="08:00:00", end_time="12:00:00")
+		date = getdate()
+		make_shift_assignment(shift_type.name, employee, date)
+
+		# shift setup for 13-15
+		shift_type = setup_shift_type(shift_type="Shift 2", start_time="11:00:00", end_time="15:00:00")
+		date = getdate()
+
+		shift2 = frappe.get_doc(
+			{
+				"doctype": "Shift Assignment",
+				"shift_type": shift_type.name,
+				"company": "_Test Company",
+				"employee": employee,
+				"start_date": date,
+			}
+		)
+		self.assertRaises(OverlappingShiftError, shift2.insert)
+
+	def test_multiple_shift_assignments_for_same_day(self):
+		employee = make_employee("test_shift_assignment@example.com", company="_Test Company")
+
+		# shift setup for 8-12
+		shift_type = setup_shift_type(shift_type="Shift 1", start_time="08:00:00", end_time="12:00:00")
+		date = getdate()
+		make_shift_assignment(shift_type.name, employee, date)
+
+		# shift setup for 13-15
+		shift_type = setup_shift_type(shift_type="Shift 2", start_time="13:00:00", end_time="15:00:00")
+		date = getdate()
+		make_shift_assignment(shift_type.name, employee, date)
+
+
+def make_shift_assignment(shift_type, employee, start_date, end_date=None):
+	shift_assignment = frappe.get_doc(
+		{
+			"doctype": "Shift Assignment",
+			"shift_type": shift_type,
+			"company": "_Test Company",
+			"employee": employee,
+			"start_date": start_date,
+			"end_date": end_date,
+		}
+	).insert()
+	shift_assignment.submit()
+
+	return shift_assignment
diff --git a/erpnext/hr/doctype/shift_type/test_shift_type.py b/erpnext/hr/doctype/shift_type/test_shift_type.py
index 7d2f29c..b91a7c3 100644
--- a/erpnext/hr/doctype/shift_type/test_shift_type.py
+++ b/erpnext/hr/doctype/shift_type/test_shift_type.py
@@ -3,6 +3,34 @@
 
 import unittest
 
+import frappe
+
 
 class TestShiftType(unittest.TestCase):
 	pass
+
+
+def setup_shift_type(**args):
+	args = frappe._dict(args)
+	shift_type = frappe.new_doc("Shift Type")
+	shift_type.__newname = args.shift_type or "_Test Shift"
+	shift_type.start_time = args.start_time or "08:00:00"
+	shift_type.end_time = args.end_time or "12:00:00"
+	shift_type.holiday_list = args.holiday_list
+	shift_type.enable_auto_attendance = 1
+
+	shift_type.determine_check_in_and_check_out = (
+		args.determine_check_in_and_check_out
+		or "Alternating entries as IN and OUT during the same shift"
+	)
+	shift_type.working_hours_calculation_based_on = (
+		args.working_hours_calculation_based_on or "First Check-in and Last Check-out"
+	)
+	shift_type.begin_check_in_before_shift_start_time = (
+		args.begin_check_in_before_shift_start_time or 60
+	)
+	shift_type.allow_check_out_after_shift_end_time = args.allow_check_out_after_shift_end_time or 60
+
+	shift_type.save()
+
+	return shift_type