def mark_absent_for_dates_with_no_attendance(self, employee): """Marks Absents for the given employee on working days in this shift which have no attendance marked. The Absent is marked starting from 'process_attendance_after' or employee creation date. """ date_of_joining, relieving_date, employee_creation = frappe.db.get_value( "Employee", employee, ["date_of_joining", "relieving_date", "creation"]) if not date_of_joining: date_of_joining = employee_creation.date() start_date = max(getdate(self.process_attendance_after), date_of_joining) actual_shift_datetime = get_actual_start_end_datetime_of_shift( employee, get_datetime(self.last_sync_of_checkin), True) last_shift_time = actual_shift_datetime[0] if actual_shift_datetime[ 0] else get_datetime(self.last_sync_of_checkin) prev_shift = get_employee_shift( employee, last_shift_time.date() - timedelta(days=1), True, 'reverse') if prev_shift: end_date = min( prev_shift.start_datetime.date(), relieving_date ) if relieving_date else prev_shift.start_datetime.date() else: return holiday_list_name = self.holiday_list if not holiday_list_name: holiday_list_name = get_holiday_list_for_employee(employee, False) dates = get_filtered_date_list(employee, start_date, end_date, holiday_list=holiday_list_name) for date in dates: shift_details = get_employee_shift(employee, date, True) if shift_details and shift_details.shift_type.name == self.name: mark_attendance(employee, date, self.name, 'Absent')
def get_start_and_end_dates(self, employee): """Returns start and end dates for checking attendance and marking absent return: start date = max of `process_attendance_after` and DOJ return: end date = min of shift before `last_sync_of_checkin` and Relieving Date """ date_of_joining, relieving_date, employee_creation = frappe.db.get_value( "Employee", employee, ["date_of_joining", "relieving_date", "creation"]) if not date_of_joining: date_of_joining = employee_creation.date() start_date = max(getdate(self.process_attendance_after), date_of_joining) end_date = None shift_details = get_shift_details( self.name, get_datetime(self.last_sync_of_checkin)) last_shift_time = (shift_details.actual_start if shift_details else get_datetime(self.last_sync_of_checkin)) # check if shift is found for 1 day before the last sync of checkin # absentees are auto-marked 1 day after the shift to wait for any manual attendance records prev_shift = get_employee_shift(employee, last_shift_time - timedelta(days=1), True, "reverse") if prev_shift: end_date = (min(prev_shift.start_datetime.date(), relieving_date) if relieving_date else prev_shift.start_datetime.date()) else: # no shift found return None, None return start_date, end_date
def mark_absent_for_dates_with_no_attendance(self, employee): """Marks Absents for the given employee on working days in this shift which have no attendance marked. The Absent is marked starting from 'process_attendance_after' or employee creation date. """ date_of_joining, relieving_date, employee_creation = frappe.db.get_value( "Employee", employee, ["date_of_joining", "relieving_date", "creation"] ) if not date_of_joining: date_of_joining = employee_creation.date() start_date = max(getdate(self.process_attendance_after), date_of_joining) actual_shift_datetime = get_actual_start_end_datetime_of_shift( employee, get_datetime(self.last_sync_of_checkin), True ) last_shift_time = ( actual_shift_datetime[0] if actual_shift_datetime[0] else get_datetime(self.last_sync_of_checkin) ) prev_shift = get_employee_shift( employee, last_shift_time.date() - timedelta(days=1), True, "reverse" ) if prev_shift: end_date = ( min(prev_shift.start_datetime.date(), relieving_date) if relieving_date else prev_shift.start_datetime.date() ) else: return holiday_list_name = self.holiday_list if not holiday_list_name: holiday_list_name = get_holiday_list_for_employee(employee, False) dates = get_filtered_date_list(employee, start_date, end_date, holiday_list=holiday_list_name) for date in dates: shift_details = get_employee_shift(employee, date, True) if shift_details and shift_details.shift_type.name == self.name: attendance = mark_attendance(employee, date, "Absent", self.name) if attendance: frappe.get_doc( { "doctype": "Comment", "comment_type": "Comment", "reference_doctype": "Attendance", "reference_name": attendance, "content": frappe._("Employee was marked Absent due to missing Employee Checkins."), } ).insert(ignore_permissions=True)
def mark_absent_for_dates_with_no_attendance(self, employee): """Marks Absents for the given employee on working days in this shift which have no attendance marked. The Absent is marked starting from 'process_attendance_after' or employee creation date. """ start_date, end_date = self.get_start_and_end_dates(employee) # no shift assignment found, no need to process absent attendance records if start_date is None: return holiday_list_name = self.holiday_list if not holiday_list_name: holiday_list_name = get_holiday_list_for_employee(employee, False) start_time = get_time(self.start_time) for date in daterange(getdate(start_date), getdate(end_date)): if is_holiday(holiday_list_name, date): # skip marking absent on a holiday continue timestamp = datetime.combine(date, start_time) shift_details = get_employee_shift(employee, timestamp, True) if shift_details and shift_details.shift_type.name == self.name: attendance = mark_attendance(employee, date, "Absent", self.name) if attendance: frappe.get_doc({ "doctype": "Comment", "comment_type": "Comment", "reference_doctype": "Attendance", "reference_name": attendance, "content": frappe. _("Employee was marked Absent due to missing Employee Checkins." ), }).insert(ignore_permissions=True)