Feature - Employee Attendance Tool

This commit is contained in:
Valmik Jangla 2016-01-27 17:43:57 +05:30 committed by Anand Doshi
parent 1890c794d7
commit 07364f5ece
6 changed files with 592 additions and 3 deletions

View File

@ -60,9 +60,9 @@ def get_data():
"items": [
{
"type": "doctype",
"name": "Process Payroll",
"label": _("Process Payroll"),
"description":_("Generate Salary Slips"),
"name": "Employee Attendance Tool",
"label": _("Employee Attendance Tool"),
"description":_("Mark Employee Attendance in Bulk"),
"hide_count": True
},
{
@ -71,6 +71,14 @@ def get_data():
"description":_("Upload attendance from a .csv file"),
"hide_count": True
},
{
"type": "doctype",
"name": "Process Payroll",
"label": _("Process Payroll"),
"description":_("Generate Salary Slips"),
"hide_count": True
},
{
"type": "doctype",
"name": "Leave Control Panel",

View File

@ -0,0 +1,21 @@
.top-toolbar{
padding-bottom: 30px;
margin-left: -17px;
}
.bottom-toolbar{
margin-left: -17px;
margin-top: 20px;
}
.btn{
margin-right: 5px;
}
.marked-employee-label{
font-weight: normal;
}
.checkbox{
margin-top: -3px;
}

View File

@ -0,0 +1,233 @@
frappe.ui.form.on("Employee Attendance Tool", {
refresh:function(frm){
frm.disable_save();
},
onload:function(frm){
erpnext.employee_attendance_tool.load_employees(frm);
},
date:function(frm){
erpnext.employee_attendance_tool.load_employees(frm);
},
department:function(frm){
erpnext.employee_attendance_tool.load_employees(frm);
},
branch:function(frm){
erpnext.employee_attendance_tool.load_employees(frm);
},
company:function(frm){
erpnext.employee_attendance_tool.load_employees(frm);
}
});
erpnext.employee_attendance_tool = {
load_employees: function(frm){
if(frm.doc.date){
frappe.call({
method:"erpnext.hr.doctype.employee_attendance_tool.employee_attendance_tool.get_employees",
args:{
date:frm.doc.date,
department:frm.doc.department,
branch:frm.doc.branch,
company:frm.doc.company
},
callback:function(r){
if(r.message['unmarked'].length > 0){
unhide_field('unmarked_attendance_section')
if(!frm.employee_area){
frm.employee_area = $('<div>')
.appendTo(frm.fields_dict.employees_html.wrapper);
}
frm.EmployeeSelector = new erpnext.EmployeeSelector(frm, frm.employee_area, r.message['unmarked'])
}
else{
hide_field('unmarked_attendance_section')
}
if(r.message['marked'].length > 0){
unhide_field('marked_attendance_section')
if(!frm.marked_employee_area){
frm.marked_employee_area = $('<div>')
.appendTo(frm.fields_dict.marked_attendance_html.wrapper);
}
frm.MarkedEmployee = new erpnext.MarkedEmployee(frm, frm.marked_employee_area, r.message['marked'])
}
else{
hide_field('marked_attendance_section')
}
}
});
}
}
}
erpnext.MarkedEmployee = Class.extend({
init: function(frm, wrapper, employee) {
this.wrapper = wrapper;
this.frm = frm;
this.make(frm, employee);
},
make: function(frm, employee) {
var me = this;
$(this.wrapper).empty();
$.each(employee, function(i, m) {
var attendance_icon = "'icon-check'"
if(m.status == "Absent") {
attendance_icon="'icon-check-empty'"
}
else if(m.status == "Half Day"){
attendance_icon = "'icon-check-minus'"
}
$(repl('<div class="col-sm-3">\
<label class="marked-employee-label"><span class=%(icon)s></span>\
%(employee)s</label>\
</div>', {employee: m.employee_name, icon: attendance_icon})).appendTo(me.wrapper);
});
}
});
erpnext.EmployeeSelector = Class.extend({
init: function(frm, wrapper, employee) {
this.wrapper = wrapper;
this.frm = frm;
this.make(frm, employee);
},
make: function(frm, employee) {
var me = this;
$(this.wrapper).empty();
var employee_toolbar = $('<div class="col-sm-12 top-toolbar">\
<button class="btn btn-default btn-add btn-xs"></button>\
<button class="btn btn-xs btn-default btn-remove"></button>\
</div>').appendTo($(this.wrapper));
var mark_employee_toolbar = $('<div class="col-sm-12 bottom-toolbar">\
<button class="btn btn-default btn-primary btn-mark-present btn-xs"></button>\
<button class="btn btn-default btn-primary btn-mark-absent btn-xs"></button>\
<button class="btn btn-default btn-primary btn-mark-half-day btn-xs"></button></div>')
employee_toolbar.find(".btn-add")
.html(__('Check all'))
.on("click", function() {
$(me.wrapper).find('input[type="checkbox"]').each(function(i, check) {
if(!$(check).is(":checked")) {
check.checked = true;
}
});
});
employee_toolbar.find(".btn-remove")
.html(__('Uncheck all'))
.on("click", function() {
$(me.wrapper).find('input[type="checkbox"]').each(function(i, check) {
if($(check).is(":checked")) {
check.checked = false;
}
});
});
mark_employee_toolbar.find(".btn-mark-present")
.html(__('Mark Present'))
.on("click", function() {
var employee_present = [];
$(me.wrapper).find('input[type="checkbox"]').each(function(i, check) {
if($(check).is(":checked")) {
employee_present.push(employee[i]);
}
});
frappe.call({
method: "erpnext.hr.doctype.employee_attendance_tool.employee_attendance_tool.mark_employee_attendance",
args:{
"employee_list":employee_present,
"status":"Present",
"date":frm.doc.date,
"company":frm.doc.company
},
callback: function(r) {
erpnext.employee_attendance_tool.load_employees(frm);
}
});
});
mark_employee_toolbar.find(".btn-mark-absent")
.html(__('Mark Absent'))
.on("click", function() {
var employee_absent = [];
$(me.wrapper).find('input[type="checkbox"]').each(function(i, check) {
if($(check).is(":checked")) {
employee_absent.push(employee[i]);
}
});
frappe.call({
method: "erpnext.hr.doctype.employee_attendance_tool.employee_attendance_tool.mark_employee_attendance",
args:{
"employee_list":employee_absent,
"status":"Absent",
"date":frm.doc.date,
"company":frm.doc.company
},
callback: function(r) {
erpnext.employee_attendance_tool.load_employees(frm);
}
});
});
mark_employee_toolbar.find(".btn-mark-half-day")
.html(__('Mark Half Day'))
.on("click", function() {
var employee_half_day = [];
$(me.wrapper).find('input[type="checkbox"]').each(function(i, check) {
if($(check).is(":checked")) {
employee_half_day.push(employee[i]);
}
});
frappe.call({
method: "erpnext.hr.doctype.employee_attendance_tool.employee_attendance_tool.mark_employee_attendance",
args:{
"employee_list":employee_half_day,
"status":"Half Day",
"date":frm.doc.date,
"company":frm.doc.company
},
callback: function(r) {
erpnext.employee_attendance_tool.load_employees(frm);
}
});
});
$.each(employee, function(i, m) {
$(repl('<div class="col-sm-3 unmarked-employee-checkbox">\
<div class="checkbox">\
<label><input type="checkbox" class="employee-check" employee="%(employee)s"/>\
%(employee)s</label>\
</div></div>', {employee: m.employee_name})).appendTo(me.wrapper);
});
mark_employee_toolbar.appendTo($(this.wrapper));
}
});

View File

@ -0,0 +1,275 @@
{
"allow_copy": 1,
"allow_import": 0,
"allow_rename": 0,
"creation": "2016-01-27 14:59:47.849379",
"custom": 0,
"docstatus": 0,
"doctype": "DocType",
"document_type": "",
"fields": [
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"default": "Today",
"fieldname": "date",
"fieldtype": "Date",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Date",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "department",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Department",
"length": 0,
"no_copy": 0,
"options": "Department",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "column_break_3",
"fieldtype": "Column Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "branch",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Branch",
"length": 0,
"no_copy": 0,
"options": "Branch",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "company",
"fieldtype": "Link",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Company",
"length": 0,
"no_copy": 0,
"options": "Company",
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"depends_on": "date",
"fieldname": "unmarked_attendance_section",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Unmarked Attendance",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "employees_html",
"fieldtype": "HTML",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Employees HTML",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"depends_on": "date",
"fieldname": "marked_attendance_section",
"fieldtype": "Section Break",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Marked Attendance",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
},
{
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"fieldname": "marked_attendance_html",
"fieldtype": "HTML",
"hidden": 0,
"ignore_user_permissions": 0,
"in_filter": 0,
"in_list_view": 0,
"label": "Marked Attendance HTML",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"unique": 0
}
],
"hide_heading": 1,
"hide_toolbar": 1,
"idx": 0,
"in_create": 0,
"in_dialog": 0,
"is_submittable": 0,
"issingle": 1,
"istable": 0,
"max_attachments": 0,
"modified": "2016-01-29 02:14:36.034952",
"modified_by": "Administrator",
"module": "HR",
"name": "Employee Attendance Tool",
"name_case": "",
"owner": "Administrator",
"permissions": [
{
"amend": 0,
"apply_user_permissions": 0,
"cancel": 0,
"create": 1,
"delete": 0,
"email": 0,
"export": 0,
"if_owner": 0,
"import": 0,
"permlevel": 0,
"print": 0,
"read": 1,
"report": 0,
"role": "HR Manager",
"set_user_permissions": 0,
"share": 0,
"submit": 0,
"write": 1
}
],
"read_only": 0,
"read_only_onload": 0,
"sort_field": "modified",
"sort_order": "DESC"
}

View File

@ -0,0 +1,52 @@
# -*- coding: utf-8 -*-
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and contributors
# For license information, please see license.txt
from __future__ import unicode_literals
import frappe
import copy
import json
from frappe.model.document import Document
class EmployeeAttendanceTool(Document):
pass
@frappe.whitelist()
def get_employees(date, department=None, branch=None, company=None):
attendance_not_marked = []
attendance_marked = []
employee_list = frappe.get_list("Employee", fields=["employee", "employee_name"], filters={
"status": "Active", "department": department, "branch": branch, "company": company}, order_by="employee_name")
marked_employee = {}
for emp in frappe.get_list("Attendance", fields=["employee", "status"],
filters={"att_date": date}):
marked_employee[emp['employee']] = emp['status']
for employee in employee_list:
employee['status'] = marked_employee.get(employee['employee'])
if employee['employee'] not in marked_employee:
attendance_not_marked.append(employee)
else:
attendance_marked.append(employee)
return {
"marked": attendance_marked,
"unmarked": attendance_not_marked
}
@frappe.whitelist()
def mark_employee_attendance(employee_list, status, date, company=None):
employee_list = json.loads(employee_list)
for employee in employee_list:
attendance = frappe.new_doc("Attendance")
attendance.employee = employee['employee']
attendance.employee_name = employee['employee_name']
attendance.att_date = date
attendance.status = status
if company:
attendance.company = company
else:
attendance.company = frappe.db.get_value("Employee", employee['employee'], "Company")
attendance.submit()