From 28fe4f3d54614a7a5714208cf0c3a4901fccb66a Mon Sep 17 00:00:00 2001 From: Rucha Mahabal Date: Tue, 17 May 2022 12:07:58 +0530 Subject: [PATCH] fix: unlink Attendance from Employee Checkins on cancellation (#31045) --- erpnext/hr/doctype/attendance/attendance.py | 30 +++++++++++++++++++ .../employee_checkin/test_employee_checkin.py | 11 +++++++ 2 files changed, 41 insertions(+) diff --git a/erpnext/hr/doctype/attendance/attendance.py b/erpnext/hr/doctype/attendance/attendance.py index e43d40ef56..f3cae8089c 100644 --- a/erpnext/hr/doctype/attendance/attendance.py +++ b/erpnext/hr/doctype/attendance/attendance.py @@ -32,6 +32,9 @@ class Attendance(Document): self.validate_employee_status() self.check_leave_record() + def on_cancel(self): + self.unlink_attendance_from_checkins() + def validate_attendance_date(self): date_of_joining = frappe.db.get_value("Employee", self.employee, "date_of_joining") @@ -127,6 +130,33 @@ class Attendance(Document): if not emp: frappe.throw(_("Employee {0} is not active or does not exist").format(self.employee)) + def unlink_attendance_from_checkins(self): + EmployeeCheckin = frappe.qb.DocType("Employee Checkin") + linked_logs = ( + frappe.qb.from_(EmployeeCheckin) + .select(EmployeeCheckin.name) + .where(EmployeeCheckin.attendance == self.name) + .for_update() + .run(as_dict=True) + ) + + if linked_logs: + ( + frappe.qb.update(EmployeeCheckin) + .set("attendance", "") + .where(EmployeeCheckin.attendance == self.name) + ).run() + + frappe.msgprint( + msg=_("Unlinked Attendance record from Employee Checkins: {}").format( + ", ".join(get_link_to_form("Employee Checkin", log.name) for log in linked_logs) + ), + title=_("Unlinked logs"), + indicator="blue", + is_minimizable=True, + wide=True, + ) + def get_duplicate_attendance_record(employee, attendance_date, shift, name=None): attendance = frappe.qb.DocType("Attendance") diff --git a/erpnext/hr/doctype/employee_checkin/test_employee_checkin.py b/erpnext/hr/doctype/employee_checkin/test_employee_checkin.py index b603b3a622..eb81f7d67c 100644 --- a/erpnext/hr/doctype/employee_checkin/test_employee_checkin.py +++ b/erpnext/hr/doctype/employee_checkin/test_employee_checkin.py @@ -76,6 +76,17 @@ class TestEmployeeCheckin(FrappeTestCase): ) self.assertEqual(attendance_count, 1) + def test_unlink_attendance_on_cancellation(self): + employee = make_employee("test_mark_attendance_and_link_log@example.com") + logs = make_n_checkins(employee, 3) + + frappe.db.delete("Attendance", {"employee": employee}) + attendance = mark_attendance_and_link_log(logs, "Present", nowdate(), 8.2) + attendance.cancel() + + linked_logs = frappe.db.get_all("Employee Checkin", {"attendance": attendance.name}) + self.assertEquals(len(linked_logs), 0) + def test_calculate_working_hours(self): check_in_out_type = [ "Alternating entries as IN and OUT during the same shift",