refactor: employee leave balance report v12 (#21282)

* fix: Employee Balance repor fixes

* refactor: Employee Leave Balance report For Version-12

Co-authored-by: Nabin Hait <nabinhait@gmail.com>
This commit is contained in:
Anurag Mishra
2020-04-26 21:05:09 +05:30
committed by GitHub
parent 5bfdf0af4d
commit 1f3584b9a8
2 changed files with 112 additions and 46 deletions

View File

@@ -8,9 +8,6 @@ from frappe.utils import flt
from erpnext.hr.doctype.leave_application.leave_application \
import get_leave_balance_on, get_leaves_for_period
from erpnext.hr.report.employee_leave_balance_summary.employee_leave_balance_summary \
import get_department_leave_approver_map
def execute(filters=None):
leave_types = frappe.db.sql_list("select name from `tabLeave Type` order by name asc")
@@ -28,6 +25,8 @@ def get_columns(leave_types):
for leave_type in leave_types:
columns.append(_(leave_type) + " " + _("Opening") + ":Float:160")
columns.append(_(leave_type) + " " + _("Allocated") + ":Float:160")
columns.append(_(leave_type) + " " + _("Expired") + ":Float:160")
columns.append(_(leave_type) + " " + _("Taken") + ":Float:160")
columns.append(_(leave_type) + " " + _("Balance") + ":Float:160")
@@ -68,18 +67,97 @@ def get_data(filters, leave_types):
row = [employee.name, employee.employee_name, employee.department]
for leave_type in leave_types:
# leaves taken
leaves_taken = get_leaves_for_period(employee.name, leave_type,
filters.from_date, filters.to_date) * -1
# opening balance
opening = get_leave_balance_on(employee.name, leave_type, filters.from_date)
# closing balance
closing = max(opening - leaves_taken, 0)
row += [opening, leaves_taken, closing]
row += calculate_leaves_details(filters, leave_type, employee)
data.append(row)
return data
return data
def calculate_leaves_details(filters, leave_type, employee):
ledger_entries = get_leave_ledger_entries(filters.from_date, filters.to_date, employee.name, leave_type)
#Leaves Deducted consist of both expired and leaves taken
leaves_deducted = get_leaves_for_period(employee.name, leave_type,
filters.from_date, filters.to_date) * -1
# removing expired leaves
leaves_taken = leaves_deducted - remove_expired_leave(ledger_entries)
opening = get_leave_balance_on(employee.name, leave_type, filters.from_date)
new_allocation , expired_allocation = get_allocated_and_expired_leaves(ledger_entries, filters.from_date, filters.to_date)
#removing leaves taken from expired_allocation
expired_leaves = max(expired_allocation - leaves_taken, 0)
#Formula for calculating closing balance
closing = max(opening + new_allocation - (leaves_taken + expired_leaves), 0)
return [opening, new_allocation, expired_leaves, leaves_taken, closing]
def remove_expired_leave(records):
expired_within_period = 0
for record in records:
if record.is_expired:
expired_within_period += record.leaves
return expired_within_period * -1
def get_allocated_and_expired_leaves(records, from_date, to_date):
from frappe.utils import getdate
new_allocation = 0
expired_leaves = 0
for record in records:
if record.to_date <= getdate(to_date) and record.leaves>0:
expired_leaves += record.leaves
if record.from_date >= getdate(from_date) and record.leaves>0:
new_allocation += record.leaves
return new_allocation, expired_leaves
def get_leave_ledger_entries(from_date, to_date, employee, leave_type):
records= frappe.db.sql("""
SELECT
employee, leave_type, from_date, to_date, leaves, transaction_name, transaction_type
is_carry_forward, is_expired
FROM `tabLeave Ledger Entry`
WHERE employee=%(employee)s AND leave_type=%(leave_type)s
AND docstatus=1
AND (from_date between %(from_date)s AND %(to_date)s
OR to_date between %(from_date)s AND %(to_date)s
OR (from_date < %(from_date)s AND to_date > %(to_date)s))
""", {
"from_date": from_date,
"to_date": to_date,
"employee": employee,
"leave_type": leave_type
}, as_dict=1)
return records
def get_department_leave_approver_map(department=None):
conditions=''
if department:
conditions="and (department_name = '%(department)s' or parent_department = '%(department)s')"%{'department': department}
# get current department and all its child
department_list = frappe.db.sql_list(""" SELECT name FROM `tabDepartment` WHERE disabled=0 {0}""".format(conditions)) #nosec
# retrieve approvers list from current department and from its subsequent child departments
approver_list = frappe.get_all('Department Approver', filters={
'parentfield': 'leave_approvers',
'parent': ('in', department_list)
}, fields=['parent', 'approver'], as_list=1)
approvers = {}
for k, v in approver_list:
approvers.setdefault(k, []).append(v)
return approvers

View File

@@ -6,6 +6,7 @@ import frappe
from frappe.utils import flt
from frappe import _
from erpnext.hr.doctype.leave_application.leave_application import get_leaves_for_period, get_leave_balance_on
from erpnext.hr.report.employee_leave_balance.employee_leave_balance import calculate_leaves_details , get_department_leave_approver_map
def execute(filters=None):
if filters.to_date <= filters.from_date:
@@ -38,17 +39,27 @@ def get_columns():
'label': _('Opening Balance'),
'fieldtype': 'float',
'fieldname': 'opening_balance',
'width': 160,
'width': 120,
}, {
'label': _('New Allocation'),
'fieldtype': 'Float',
'fieldname': 'new_allocation',
'width': 120,
}, {
'label': _('Expired Leaves'),
'fieldtype': 'Float',
'fieldname': 'expired_leaves',
'width': 120,
}, {
'label': _('Leaves Taken'),
'fieldtype': 'float',
'fieldname': 'leaves_taken',
'width': 160,
'width': 120,
}, {
'label': _('Closing Balance'),
'fieldtype': 'float',
'fieldname': 'closing_balance',
'width': 160,
'width': 120,
}]
return columns
@@ -72,7 +83,7 @@ def get_data(filters):
'leave_type': leave_type
})
for employee in active_employees:
leave_approvers = department_approver_map.get(employee.department_name, []).append(employee.leave_approver)
if (leave_approvers and len(leave_approvers) and user in leave_approvers) or (user in ["Administrator", employee.user_id]) \
@@ -82,16 +93,13 @@ def get_data(filters):
'employee_name': employee.employee_name
})
leaves_taken = get_leaves_for_period(employee.name, leave_type,
filters.from_date, filters.to_date) * -1
leave_details = calculate_leaves_details(filters, leave_type, employee)
row.opening_balance = flt(leave_details[0])
row.new_allocation = flt(leave_details[1])
row.expired_leaves = flt(leave_details[2])
row.leaves_taken = flt(leave_details[3])
row.closing_balance = flt(leave_details[4])
opening = get_leave_balance_on(employee.name, leave_type, filters.from_date)
closing = get_leave_balance_on(employee.name, leave_type, filters.to_date)
row.opening_balance = opening
row.leaves_taken = leaves_taken
row.closing_balance = closing
row.indent = 1
data.append(row)
return data
@@ -108,23 +116,3 @@ def get_conditions(filters):
return conditions
def get_department_leave_approver_map(department=None):
conditions=''
if department:
conditions="and (department_name = '%(department)s' or parent_department = '%(department)s')"%{'department': department}
# get current department and all its child
department_list = frappe.db.sql_list(""" SELECT name FROM `tabDepartment` WHERE disabled=0 {0}""".format(conditions)) #nosec
# retrieve approvers list from current department and from its subsequent child departments
approver_list = frappe.get_all('Department Approver', filters={
'parentfield': 'leave_approvers',
'parent': ('in', department_list)
}, fields=['parent', 'approver'], as_list=1)
approvers = {}
for k, v in approver_list:
approvers.setdefault(k, []).append(v)
return approvers