fix(hr): Auto Attendance
> fixing minor bug in shift calculation > adding 'Mark Auto Attendance' button in shift and related fixes > changed employee checkin naming series > added aditional validation for employee checkin > added/updated dashboard for Attendance, Employee, Shift Type
This commit is contained in:
parent
32197355ad
commit
82256bc58b
13
erpnext/hr/doctype/attendance/attendance_dashboard.py
Normal file
13
erpnext/hr/doctype/attendance/attendance_dashboard.py
Normal file
@ -0,0 +1,13 @@
|
||||
from __future__ import unicode_literals
|
||||
from frappe import _
|
||||
|
||||
def get_data():
|
||||
return {
|
||||
'fieldname': 'attendance',
|
||||
'transactions': [
|
||||
{
|
||||
'label': '',
|
||||
'items': ['Employee Checkin']
|
||||
}
|
||||
]
|
||||
}
|
@ -9,7 +9,7 @@ def get_data():
|
||||
'transactions': [
|
||||
{
|
||||
'label': _('Leave and Attendance'),
|
||||
'items': ['Attendance', 'Attendance Request', 'Leave Application', 'Leave Allocation']
|
||||
'items': ['Attendance', 'Attendance Request', 'Leave Application', 'Leave Allocation', 'Employee Checkin']
|
||||
},
|
||||
{
|
||||
'label': _('Lifecycle'),
|
||||
@ -40,4 +40,4 @@ def get_data():
|
||||
'items': ['Training Event', 'Training Result', 'Training Feedback', 'Employee Skill Map']
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"allow_import": 1,
|
||||
"autoname": "ATT-CKIN-.MM.-.YYYY.-.######",
|
||||
"autoname": "EMP-CKIN-.MM.-.YYYY.-.######",
|
||||
"creation": "2019-06-10 11:56:34.536413",
|
||||
"doctype": "DocType",
|
||||
"engine": "InnoDB",
|
||||
@ -119,7 +119,7 @@
|
||||
"label": "Shift Actual End"
|
||||
}
|
||||
],
|
||||
"modified": "2019-06-10 11:56:34.536413",
|
||||
"modified": "2019-06-10 15:33:22.731697",
|
||||
"modified_by": "Administrator",
|
||||
"module": "HR",
|
||||
"name": "Employee Checkin",
|
||||
|
@ -28,6 +28,8 @@ class EmployeeCheckin(Document):
|
||||
def fetch_shift(self):
|
||||
shift_actual_timings = get_actual_start_end_datetime_of_shift(self.employee, get_datetime(self.time), True)
|
||||
if shift_actual_timings[0] and shift_actual_timings[1]:
|
||||
if shift_actual_timings[2].shift_type.determine_check_in_and_check_out == 'Strictly based on Log Type in Employee Checkin' and not self.log_type and not self.skip_auto_attendance:
|
||||
frappe.throw(_('Log Type is required for check-ins falling in the shift: {0}.').format(shift_actual_timings[2].shift_type.name))
|
||||
if not self.attendance:
|
||||
self.shift = shift_actual_timings[2].shift_type.name
|
||||
self.shift_actual_start = shift_actual_timings[0]
|
||||
|
@ -115,11 +115,12 @@ def get_employee_shift(employee, for_date=nowdate(), consider_default_shift=Fals
|
||||
break
|
||||
else:
|
||||
direction = '<' if next_shift_direction == 'reverse' else '>'
|
||||
sort_order = 'desc' if next_shift_direction == 'reverse' else 'asc'
|
||||
dates = frappe.db.get_all('Shift Assignment',
|
||||
'date',
|
||||
{'employee':employee, 'date':(direction, for_date), 'docstatus': '1'},
|
||||
as_list=True,
|
||||
limit=MAX_DAYS)
|
||||
limit=MAX_DAYS, order_by="date "+sort_order)
|
||||
for date in dates:
|
||||
shift_details = get_employee_shift(employee, date[0], consider_default_shift, None)
|
||||
if shift_details:
|
||||
|
@ -3,6 +3,16 @@
|
||||
|
||||
frappe.ui.form.on('Shift Type', {
|
||||
refresh: function(frm) {
|
||||
|
||||
frm.add_custom_button(
|
||||
'Mark Auto Attendance',
|
||||
() => frm.call({
|
||||
doc: frm.doc,
|
||||
method: 'process_auto_attendance',
|
||||
freeze: true,
|
||||
callback: () => {
|
||||
frappe.msgprint(__("Attendance has been marked as per employee check-ins"));
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
});
|
||||
|
@ -8,7 +8,7 @@ from datetime import timedelta
|
||||
|
||||
import frappe
|
||||
from frappe.model.document import Document
|
||||
from frappe.utils import cint, getdate
|
||||
from frappe.utils import cint, getdate, get_datetime
|
||||
from erpnext.hr.doctype.shift_assignment.shift_assignment import get_actual_start_end_datetime_of_shift, get_employee_shift
|
||||
from erpnext.hr.doctype.employee_checkin.employee_checkin import mark_attendance_and_link_log, calculate_working_hours
|
||||
from erpnext.hr.doctype.attendance.attendance import mark_absent
|
||||
@ -53,9 +53,9 @@ class ShiftType(Document):
|
||||
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(self.process_attendance_after, date_of_joining)
|
||||
actual_shift_datetime = get_actual_start_end_datetime_of_shift(employee, self.last_sync_of_checkin, True)
|
||||
last_shift_time = actual_shift_datetime[0] if actual_shift_datetime[0] else self.last_sync_of_checkin
|
||||
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()
|
||||
@ -64,10 +64,11 @@ class ShiftType(Document):
|
||||
holiday_list_name = self.holiday_list
|
||||
if not holiday_list_name:
|
||||
holiday_list_name = get_holiday_list_for_employee(employee, False)
|
||||
for date in get_filtered_date_list(employee, start_date, end_date, holiday_list=holiday_list_name):
|
||||
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_absent(employee, date)
|
||||
mark_absent(employee, date, self.name)
|
||||
|
||||
def get_assigned_employee(self, from_date=None, consider_default_shift=False):
|
||||
filters = {'date':('>=', from_date), 'shift_type': self.name, 'docstatus': '1'}
|
||||
|
@ -2,11 +2,11 @@ from __future__ import unicode_literals
|
||||
from frappe import _
|
||||
|
||||
def get_data():
|
||||
return {
|
||||
'fieldname': 'shift_type',
|
||||
'transactions': [
|
||||
{
|
||||
'items': ['Shift Request', 'Shift Assignment']
|
||||
}
|
||||
],
|
||||
}
|
||||
return {
|
||||
'fieldname': 'shift',
|
||||
'transactions': [
|
||||
{
|
||||
'items': ['Attendance', 'Employee Checkin', 'Shift Request', 'Shift Assignment']
|
||||
}
|
||||
]
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user