예제 #1
0
    def test_overlap_for_request_without_to_date(self):
        # shift should be Ongoing if Only from_date is present
        user = "******"
        employee = make_employee(user,
                                 company="_Test Company",
                                 shift_request_approver=user)
        setup_shift_type(shift_type="Day Shift")

        shift_request = frappe.get_doc({
            "doctype": "Shift Request",
            "shift_type": "Day Shift",
            "company": "_Test Company",
            "employee": employee,
            "from_date": nowdate(),
            "approver": user,
            "status": "Approved",
        }).submit()

        shift_request = frappe.get_doc({
            "doctype": "Shift Request",
            "shift_type": "Day Shift",
            "company": "_Test Company",
            "employee": employee,
            "from_date": add_days(nowdate(), 2),
            "approver": user,
            "status": "Approved",
        })

        self.assertRaises(OverlappingShiftRequestError, shift_request.save)
예제 #2
0
    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",
            "shift_type": "Day Shift",
            "company": "_Test Company",
            "employee": "_T-Employee-00001",
            "start_date": nowdate(),
            "end_date": add_days(nowdate(), 30),
            "status": "Active",
        }).insert()
        shift_assignment_1.submit()

        # it should not allowed within period of any shift.
        shift_assignment_3 = frappe.get_doc({
            "doctype":
            "Shift Assignment",
            "shift_type":
            "Day Shift",
            "company":
            "_Test Company",
            "employee":
            "_T-Employee-00001",
            "start_date":
            add_days(nowdate(), 10),
            "end_date":
            add_days(nowdate(), 35),
            "status":
            "Active",
        })

        self.assertRaises(OverlappingShiftError, shift_assignment_3.save)
예제 #3
0
    def test_overlapping_for_a_fixed_period_shift_and_ongoing_shift(self):
        employee = make_employee("*****@*****.**",
                                 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 11-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)
예제 #4
0
    def test_fetch_shift_for_assignment_with_end_date(self):
        employee = make_employee("*****@*****.**",
                                 company="_Test Company")

        # shift setup for 8-12
        shift1 = setup_shift_type()
        # 12:30 - 16:30
        shift2 = setup_shift_type(shift_type="Shift 2",
                                  start_time="12:30:00",
                                  end_time="16:30:00")

        date = getdate()
        make_shift_assignment(shift1.name, employee, date, add_days(date, 15))
        make_shift_assignment(shift2.name, employee, date, add_days(date, 15))

        timestamp = datetime.combine(date, get_time("08:45:00"))
        log = make_checkin(employee, timestamp)
        self.assertEqual(log.shift, shift1.name)

        timestamp = datetime.combine(date, get_time("12:45:00"))
        log = make_checkin(employee, timestamp)
        self.assertEqual(log.shift, shift2.name)

        # log after end date
        timestamp = datetime.combine(add_days(date, 16), get_time("12:45:00"))
        log = make_checkin(employee, timestamp)
        self.assertIsNone(log.shift)
예제 #5
0
    def test_make_shift_request(self):
        "Test creation/updation of Shift Assignment from Shift Request."
        setup_shift_type(shift_type="Day Shift")
        department = frappe.get_value("Employee", "_T-Employee-00001",
                                      "department")
        set_shift_approver(department)
        approver = frappe.db.sql(
            """select approver from `tabDepartment Approver` where parent= %s and parentfield = 'shift_request_approver'""",
            (department),
        )[0][0]

        shift_request = make_shift_request(approver)

        # Only one shift assignment is created against a shift request
        shift_assignment = frappe.db.get_value(
            "Shift Assignment",
            filters={"shift_request": shift_request.name},
            fieldname=["employee", "docstatus"],
            as_dict=True,
        )
        self.assertEqual(shift_request.employee, shift_assignment.employee)
        self.assertEqual(shift_assignment.docstatus, 1)

        shift_request.cancel()

        shift_assignment_docstatus = frappe.db.get_value(
            "Shift Assignment",
            filters={"shift_request": shift_request.name},
            fieldname="docstatus")
        self.assertEqual(shift_assignment_docstatus, 2)
예제 #6
0
    def test_overlap_validation_for_shifts_on_same_day_with_overlapping_timeslots(
            self):
        employee = make_employee("*****@*****.**",
                                 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 11-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)
예제 #7
0
    def test_make_shift_assignment(self):
        setup_shift_type(shift_type="Day Shift")
        shift_assignment = frappe.get_doc({
            "doctype": "Shift Assignment",
            "shift_type": "Day Shift",
            "company": "_Test Company",
            "employee": "_T-Employee-00001",
            "start_date": nowdate(),
        }).insert()
        shift_assignment.submit()

        self.assertEqual(shift_assignment.docstatus, 1)
예제 #8
0
	def test_duplicate_attendance_with_shift(self):
		from erpnext.hr.doctype.shift_type.test_shift_type import setup_shift_type

		employee = make_employee("*****@*****.**", 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)
예제 #9
0
    def test_fetch_shift(self):
        employee = make_employee("*****@*****.**",
                                 company="_Test Company")

        # shift setup for 8-12
        shift_type = setup_shift_type()
        date = getdate()
        make_shift_assignment(shift_type.name, employee, date)

        # within shift time
        timestamp = datetime.combine(date, get_time("08:45:00"))
        log = make_checkin(employee, timestamp)
        self.assertEqual(log.shift, shift_type.name)

        # "begin checkin before shift time" = 60 mins, so should work for 7:00:00
        timestamp = datetime.combine(date, get_time("07:00:00"))
        log = make_checkin(employee, timestamp)
        self.assertEqual(log.shift, shift_type.name)

        # "allow checkout after shift end time" = 60 mins, so should work for 13:00:00
        timestamp = datetime.combine(date, get_time("13:00:00"))
        log = make_checkin(employee, timestamp)
        self.assertEqual(log.shift, shift_type.name)

        # should not fetch this shift beyond allowed time
        timestamp = datetime.combine(date, get_time("13:01:00"))
        log = make_checkin(employee, timestamp)
        self.assertIsNone(log.shift)
예제 #10
0
    def test_no_shift_fetched_on_holiday_as_per_shift_holiday_list(self):
        date = getdate()
        from_date = get_year_start(date)
        to_date = get_year_ending(date)
        holiday_list = make_holiday_list(from_date=from_date, to_date=to_date)

        employee = make_employee("*****@*****.**",
                                 company="_Test Company")
        setup_shift_type(shift_type="Test Holiday Shift",
                         holiday_list=holiday_list)

        first_sunday = get_first_sunday(holiday_list, for_date=date)
        timestamp = datetime.combine(first_sunday, get_time("08:00:00"))
        log = make_checkin(employee, timestamp)

        self.assertIsNone(log.shift)
예제 #11
0
    def test_multiple_shift_assignments_for_same_day(self):
        employee = make_employee("*****@*****.**",
                                 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)
예제 #12
0
    def test_shift_request_approver_perms(self):
        setup_shift_type(shift_type="Day Shift")
        employee = frappe.get_doc("Employee", "_T-Employee-00001")
        user = "******"
        make_employee(user, "_Test Company")

        # set approver for employee
        employee.reload()
        employee.shift_request_approver = user
        employee.save()

        shift_request = make_shift_request(user, do_not_submit=True)
        self.assertTrue(shift_request.name in frappe.share.get_shared(
            "Shift Request", user))

        # check shared doc revoked
        shift_request.reload()
        department = frappe.get_value("Employee", "_T-Employee-00001",
                                      "department")
        set_shift_approver(department)
        department_approver = frappe.db.sql(
            """select approver from `tabDepartment Approver` where parent= %s and parentfield = 'shift_request_approver'""",
            (department),
        )[0][0]
        shift_request.approver = department_approver
        shift_request.save()
        self.assertTrue(shift_request.name not in frappe.share.get_shared(
            "Shift Request", user))

        shift_request.reload()
        shift_request.approver = user
        shift_request.save()

        frappe.set_user(user)
        shift_request.reload()
        shift_request.status = "Approved"
        shift_request.submit()

        # unset approver
        frappe.set_user("Administrator")
        employee.reload()
        employee.shift_request_approver = ""
        employee.save()
예제 #13
0
    def test_consecutive_shift_assignments_overlapping_within_grace_period(
            self):
        # test adjustment for start and end times if they are overlapping
        # within "begin_check_in_before_shift_start_time" and "allow_check_out_after_shift_end_time" periods
        employee = make_employee("*****@*****.**",
                                 company="_Test Company")

        # 8 - 12
        shift1 = setup_shift_type()
        # 12:30 - 16:30
        shift2 = setup_shift_type(shift_type="Consecutive Shift",
                                  start_time="12:30:00",
                                  end_time="16:30:00")

        # the actual start and end times (with grace) for these shifts are 7 - 13 and 11:30 - 17:30
        date = getdate()
        make_shift_assignment(shift1.name, employee, date)
        make_shift_assignment(shift2.name, employee, date)

        # log at 12:30 should set shift2 and actual start as 12 and not 11:30
        timestamp = datetime.combine(date, get_time("12:30:00"))
        log = make_checkin(employee, timestamp)
        self.assertEqual(log.shift, shift2.name)
        self.assertEqual(log.shift_start,
                         datetime.combine(date, get_time("12:30:00")))
        self.assertEqual(log.shift_actual_start,
                         datetime.combine(date, get_time("12:00:00")))

        # log at 12:00 should set shift1 and actual end as 12 and not 1 since the next shift's grace starts
        timestamp = datetime.combine(date, get_time("12:00:00"))
        log = make_checkin(employee, timestamp)
        self.assertEqual(log.shift, shift1.name)
        self.assertEqual(log.shift_end,
                         datetime.combine(date, get_time("12:00:00")))
        self.assertEqual(log.shift_actual_end,
                         datetime.combine(date, get_time("12:00:00")))

        # log at 12:01 should set shift2
        timestamp = datetime.combine(date, get_time("12:01:00"))
        log = make_checkin(employee, timestamp)
        self.assertEqual(log.shift, shift2.name)
예제 #14
0
	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("*****@*****.**", 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)
		frappe.get_doc(
			{
				"doctype": "Attendance",
				"employee": employee,
				"attendance_date": date,
				"status": "Absent",
				"company": "_Test Company",
				"shift": shift_2.name,
			}
		).insert()
예제 #15
0
    def test_overlapping_for_a_fixed_period_shift_and_ongoing_shift(self):
        user = "******"
        employee = make_employee(user,
                                 company="_Test Company",
                                 shift_request_approver=user)

        # 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 = nowdate()

        # shift with end date
        frappe.get_doc({
            "doctype": "Shift Request",
            "shift_type": shift_type.name,
            "company": "_Test Company",
            "employee": employee,
            "from_date": date,
            "to_date": add_days(date, 30),
            "approver": user,
            "status": "Approved",
        }).submit()

        # shift setup for 11-15
        shift_type = setup_shift_type(shift_type="Shift 2",
                                      start_time="11:00:00",
                                      end_time="15:00:00")
        shift2 = frappe.get_doc({
            "doctype": "Shift Request",
            "shift_type": shift_type.name,
            "company": "_Test Company",
            "employee": employee,
            "from_date": date,
            "approver": user,
            "status": "Approved",
        })

        self.assertRaises(OverlappingShiftRequestError, shift2.insert)
예제 #16
0
    def test_no_shift_fetched_on_holiday_as_per_employee_holiday_list(self):
        employee = make_employee("*****@*****.**",
                                 company="_Test Company")
        shift_type = setup_shift_type(shift_type="Test Holiday Shift")
        shift_type.holiday_list = None
        shift_type.save()

        date = getdate()

        first_sunday = get_first_sunday(self.holiday_list, for_date=date)
        timestamp = datetime.combine(first_sunday, get_time("08:00:00"))
        log = make_checkin(employee, timestamp)

        self.assertIsNone(log.shift)
예제 #17
0
    def test_allow_non_overlapping_shift_requests_for_same_day(self):
        user = "******"
        employee = make_employee(user,
                                 company="_Test Company",
                                 shift_request_approver=user)

        # 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 = nowdate()

        # shift with end date
        frappe.get_doc({
            "doctype": "Shift Request",
            "shift_type": shift_type.name,
            "company": "_Test Company",
            "employee": employee,
            "from_date": date,
            "to_date": add_days(date, 30),
            "approver": user,
            "status": "Approved",
        }).submit()

        # shift setup for 13-15
        shift_type = setup_shift_type(shift_type="Shift 2",
                                      start_time="13:00:00",
                                      end_time="15:00:00")
        frappe.get_doc({
            "doctype": "Shift Request",
            "shift_type": shift_type.name,
            "company": "_Test Company",
            "employee": employee,
            "from_date": date,
            "approver": user,
            "status": "Approved",
        }).submit()
예제 #18
0
    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",
            "shift_type": "Day Shift",
            "company": "_Test Company",
            "employee": "_T-Employee-00001",
            "start_date": nowdate(),
            "status": "Active",
        }).insert()
        shift_assignment_1.submit()

        self.assertEqual(shift_assignment_1.docstatus, 1)

        shift_assignment = frappe.get_doc({
            "doctype": "Shift Assignment",
            "shift_type": "Day Shift",
            "company": "_Test Company",
            "employee": "_T-Employee-00001",
            "start_date": add_days(nowdate(), 2),
        })

        self.assertRaises(OverlappingShiftError, shift_assignment.save)
예제 #19
0
	def test_overlapping_shift_attendance_validation(self):
		from erpnext.hr.doctype.shift_type.test_shift_type import setup_shift_type

		employee = make_employee("*****@*****.**", 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)
예제 #20
0
    def test_fetch_shift_based_on_default_shift(self):
        employee = make_employee("*****@*****.**",
                                 company="_Test Company")
        default_shift = setup_shift_type(shift_type="Default Shift",
                                         start_time="14:00:00",
                                         end_time="16:00:00")

        date = getdate()
        frappe.db.set_value("Employee", employee, "default_shift",
                            default_shift.name)

        timestamp = datetime.combine(date, get_time("14:45:00"))
        log = make_checkin(employee, timestamp)

        # should consider default shift
        self.assertEqual(log.shift, default_shift.name)
예제 #21
0
    def test_shift_assignment_calendar(self):
        employee1 = make_employee("*****@*****.**",
                                  company="_Test Company")
        employee2 = make_employee("*****@*****.**",
                                  company="_Test Company")

        shift_type = setup_shift_type(shift_type="Shift 1",
                                      start_time="08:00:00",
                                      end_time="12:00:00")
        date = getdate()
        shift1 = make_shift_assignment(shift_type.name, employee1, date)
        make_shift_assignment(shift_type.name, employee2, date)

        events = get_events(
            start=date,
            end=date,
            filters=[["Shift Assignment", "employee", "=", employee1, False]])
        self.assertEqual(len(events), 1)
        self.assertEqual(events[0]["name"], shift1.name)
예제 #22
0
    def test_shift_start_and_end_timings(self):
        employee = make_employee("*****@*****.**",
                                 company="_Test Company")

        # shift setup for 8-12
        shift_type = setup_shift_type()
        date = getdate()
        make_shift_assignment(shift_type.name, employee, date)

        timestamp = datetime.combine(date, get_time("08:45:00"))
        log = make_checkin(employee, timestamp)

        self.assertEqual(log.shift, shift_type.name)
        self.assertEqual(log.shift_start,
                         datetime.combine(date, get_time("08:00:00")))
        self.assertEqual(log.shift_end,
                         datetime.combine(date, get_time("12:00:00")))
        self.assertEqual(log.shift_actual_start,
                         datetime.combine(date, get_time("07:00:00")))
        self.assertEqual(log.shift_actual_end,
                         datetime.combine(date, get_time("13:00:00")))
예제 #23
0
    def test_fetch_shift_spanning_over_two_days(self):
        employee = make_employee("*****@*****.**",
                                 company="_Test Company")
        shift_type = setup_shift_type(shift_type="Midnight Shift",
                                      start_time="23:00:00",
                                      end_time="01:00:00")
        date = getdate()
        next_day = add_days(date, 1)
        make_shift_assignment(shift_type.name, employee, date)

        # log falls in the first day
        timestamp = datetime.combine(date, get_time("23:00:00"))
        log = make_checkin(employee, timestamp)

        self.assertEqual(log.shift, shift_type.name)
        self.assertEqual(log.shift_start,
                         datetime.combine(date, get_time("23:00:00")))
        self.assertEqual(log.shift_end,
                         datetime.combine(next_day, get_time("01:00:00")))
        self.assertEqual(log.shift_actual_start,
                         datetime.combine(date, get_time("22:00:00")))
        self.assertEqual(log.shift_actual_end,
                         datetime.combine(next_day, get_time("02:00:00")))

        log.delete()

        # log falls in the second day
        prev_day = add_days(date, -1)
        timestamp = datetime.combine(date, get_time("01:30:00"))
        log = make_checkin(employee, timestamp)
        self.assertEqual(log.shift, shift_type.name)
        self.assertEqual(log.shift_start,
                         datetime.combine(prev_day, get_time("23:00:00")))
        self.assertEqual(log.shift_end,
                         datetime.combine(date, get_time("01:00:00")))
        self.assertEqual(log.shift_actual_start,
                         datetime.combine(prev_day, get_time("22:00:00")))
        self.assertEqual(log.shift_actual_end,
                         datetime.combine(date, get_time("02:00:00")))