From 277bda11dda30ab28735c3ce575c06ea4eb95152 Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Mon, 4 Apr 2022 11:04:24 +0530 Subject: [PATCH] test: validations for duplicate and overlapping shift attendance records --- .../hr/doctype/attendance/test_attendance.py | 109 +++++++++++++++++- 1 file changed, 104 insertions(+), 5 deletions(-) diff --git a/erpnext/hr/doctype/attendance/test_attendance.py b/erpnext/hr/doctype/attendance/test_attendance.py index 058bc93d72..ecd14c8a9b 100644 --- a/erpnext/hr/doctype/attendance/test_attendance.py +++ b/erpnext/hr/doctype/attendance/test_attendance.py @@ -6,6 +6,8 @@ from frappe.tests.utils import FrappeTestCase from frappe.utils import add_days, get_year_ending, get_year_start, getdate, now_datetime, nowdate from erpnext.hr.doctype.attendance.attendance import ( + DuplicateAttendanceError, + OverlappingShiftAttendanceError, get_month_map, get_unmarked_days, mark_attendance, @@ -23,11 +25,112 @@ class TestAttendance(FrappeTestCase): from_date = get_year_start(getdate()) to_date = get_year_ending(getdate()) self.holiday_list = make_holiday_list(from_date=from_date, to_date=to_date) + frappe.db.delete("Attendance") + + def test_duplicate_attendance(self): + employee = make_employee("test_duplicate_attendance@example.com", company="_Test Company") + date = nowdate() + + mark_attendance(employee, date, "Present") + attendance = frappe.get_doc( + { + "doctype": "Attendance", + "employee": employee, + "attendance_date": date, + "status": "Absent", + "company": "_Test Company", + } + ) + + self.assertRaises(DuplicateAttendanceError, attendance.insert) + + def test_duplicate_attendance_with_shift(self): + from erpnext.hr.doctype.shift_type.test_shift_type import setup_shift_type + + employee = make_employee("test_duplicate_attendance@example.com", company="_Test Company") + date = nowdate() + + shift_1 = setup_shift_type(shift_type="Shift 1", start_time="08:00:00", end_time="10:00:00") + mark_attendance(employee, date, "Present", shift=shift_1.name) + + # attendance record with shift + attendance = frappe.get_doc( + { + "doctype": "Attendance", + "employee": employee, + "attendance_date": date, + "status": "Absent", + "company": "_Test Company", + "shift": shift_1.name, + } + ) + + self.assertRaises(DuplicateAttendanceError, attendance.insert) + + # attendance record without any shift + attendance = frappe.get_doc( + { + "doctype": "Attendance", + "employee": employee, + "attendance_date": date, + "status": "Absent", + "company": "_Test Company", + } + ) + + self.assertRaises(DuplicateAttendanceError, attendance.insert) + + def test_overlapping_shift_attendance_validation(self): + from erpnext.hr.doctype.shift_type.test_shift_type import setup_shift_type + + employee = make_employee("test_overlap_attendance@example.com", company="_Test Company") + date = nowdate() + + shift_1 = setup_shift_type(shift_type="Shift 1", start_time="08:00:00", end_time="10:00:00") + shift_2 = setup_shift_type(shift_type="Shift 2", start_time="09:30:00", end_time="11:00:00") + + mark_attendance(employee, date, "Present", shift=shift_1.name) + + # attendance record with overlapping shift + attendance = frappe.get_doc( + { + "doctype": "Attendance", + "employee": employee, + "attendance_date": date, + "status": "Absent", + "company": "_Test Company", + "shift": shift_2.name, + } + ) + + self.assertRaises(OverlappingShiftAttendanceError, attendance.insert) + + def test_allow_attendance_with_different_shifts(self): + # allows attendance with 2 different non-overlapping shifts + from erpnext.hr.doctype.shift_type.test_shift_type import setup_shift_type + + employee = make_employee("test_duplicate_attendance@example.com", company="_Test Company") + date = nowdate() + + shift_1 = setup_shift_type(shift_type="Shift 1", start_time="08:00:00", end_time="10:00:00") + shift_2 = setup_shift_type(shift_type="Shift 2", start_time="11:00:00", end_time="12:00:00") + + mark_attendance(employee, date, "Present", shift_1.name) + attendance = frappe.get_doc( + { + "doctype": "Attendance", + "employee": employee, + "attendance_date": date, + "status": "Absent", + "company": "_Test Company", + "shift": shift_2.name, + } + ).insert() def test_mark_absent(self): employee = make_employee("test_mark_absent@example.com") date = nowdate() - frappe.db.delete("Attendance", {"employee": employee, "attendance_date": date}) + attendance = mark_attendance(employee, date, "Absent") fetch_attendance = frappe.get_value( "Attendance", {"employee": employee, "attendance_date": date, "status": "Absent"} @@ -42,7 +145,6 @@ class TestAttendance(FrappeTestCase): employee = make_employee( "test_unmarked_days@example.com", date_of_joining=add_days(first_day, -1) ) - frappe.db.delete("Attendance", {"employee": employee}) frappe.db.set_value("Employee", employee, "holiday_list", self.holiday_list) first_sunday = get_first_sunday(self.holiday_list, for_date=first_day) @@ -67,8 +169,6 @@ class TestAttendance(FrappeTestCase): employee = make_employee( "test_unmarked_days@example.com", date_of_joining=add_days(first_day, -1) ) - frappe.db.delete("Attendance", {"employee": employee}) - frappe.db.set_value("Employee", employee, "holiday_list", self.holiday_list) first_sunday = get_first_sunday(self.holiday_list, for_date=first_day) @@ -95,7 +195,6 @@ class TestAttendance(FrappeTestCase): employee = make_employee( "test_unmarked_days_as_per_doj@example.com", date_of_joining=doj, relieving_date=relieving_date ) - frappe.db.delete("Attendance", {"employee": employee}) frappe.db.set_value("Employee", employee, "holiday_list", self.holiday_list)