fix: leave balance reports (#18984)
* fix: process allocation expiry * fix: leave balance summary filter * fix: opening and closing balance * fix: check for department leave approvers * fix: minor changes * fix: consider leave approver in employee * Update employee_leave_balance_summary.py
This commit is contained in:
parent
72949e7f73
commit
755020843b
@ -8,6 +8,8 @@ from frappe.utils import flt
|
|||||||
from erpnext.hr.doctype.leave_application.leave_application \
|
from erpnext.hr.doctype.leave_application.leave_application \
|
||||||
import get_leave_balance_on, get_leaves_for_period
|
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):
|
def execute(filters=None):
|
||||||
leave_types = frappe.db.sql_list("select name from `tabLeave Type` order by name asc")
|
leave_types = frappe.db.sql_list("select name from `tabLeave Type` order by name asc")
|
||||||
@ -19,7 +21,7 @@ def execute(filters=None):
|
|||||||
|
|
||||||
def get_columns(leave_types):
|
def get_columns(leave_types):
|
||||||
columns = [
|
columns = [
|
||||||
_("Employee") + ":Link/Employee:150",
|
_("Employee") + ":Link.Employee:150",
|
||||||
_("Employee Name") + "::200",
|
_("Employee Name") + "::200",
|
||||||
_("Department") +"::150"
|
_("Department") +"::150"
|
||||||
]
|
]
|
||||||
@ -52,11 +54,13 @@ def get_data(filters, leave_types):
|
|||||||
|
|
||||||
active_employees = frappe.get_all("Employee",
|
active_employees = frappe.get_all("Employee",
|
||||||
filters=conditions,
|
filters=conditions,
|
||||||
fields=["name", "employee_name", "department", "user_id"])
|
fields=["name", "employee_name", "department", "user_id", "leave_approver"])
|
||||||
|
|
||||||
|
department_approver_map = get_department_leave_approver_map(filters.get('department'))
|
||||||
|
|
||||||
data = []
|
data = []
|
||||||
for employee in active_employees:
|
for employee in active_employees:
|
||||||
leave_approvers = get_approvers(employee.department)
|
leave_approvers = department_approver_map.get(employee.department_name, []).append(employee.leave_approver)
|
||||||
if (len(leave_approvers) and user in leave_approvers) or (user in ["Administrator", employee.user_id]) or ("HR Manager" in frappe.get_roles(user)):
|
if (len(leave_approvers) and user in leave_approvers) or (user in ["Administrator", employee.user_id]) or ("HR Manager" in frappe.get_roles(user)):
|
||||||
row = [employee.name, employee.employee_name, employee.department]
|
row = [employee.name, employee.employee_name, employee.department]
|
||||||
|
|
||||||
@ -66,46 +70,13 @@ def get_data(filters, leave_types):
|
|||||||
filters.from_date, filters.to_date) * -1
|
filters.from_date, filters.to_date) * -1
|
||||||
|
|
||||||
# opening balance
|
# opening balance
|
||||||
opening = get_total_allocated_leaves(employee.name, leave_type, filters.from_date, filters.to_date)
|
opening = get_leave_balance_on(employee.name, leave_type, filters.from_date)
|
||||||
|
|
||||||
# closing balance
|
# closing balance
|
||||||
closing = flt(opening) - flt(leaves_taken)
|
closing = get_leave_balance_on(employee.name, leave_type, filters.to_date)
|
||||||
|
|
||||||
row += [opening, leaves_taken, closing]
|
row += [opening, leaves_taken, closing]
|
||||||
|
|
||||||
data.append(row)
|
data.append(row)
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def get_approvers(department):
|
|
||||||
if not department:
|
|
||||||
return []
|
|
||||||
|
|
||||||
approvers = []
|
|
||||||
# get current department and all its child
|
|
||||||
department_details = frappe.db.get_value("Department", {"name": department}, ["lft", "rgt"], as_dict=True)
|
|
||||||
department_list = frappe.db.sql("""select name from `tabDepartment`
|
|
||||||
where lft >= %s and rgt <= %s order by lft desc
|
|
||||||
""", (department_details.lft, department_details.rgt), as_list = True)
|
|
||||||
|
|
||||||
# retrieve approvers list from current department and from its subsequent child departments
|
|
||||||
for d in department_list:
|
|
||||||
approvers.extend([l.leave_approver for l in frappe.db.sql("""select approver from `tabDepartment Approver` \
|
|
||||||
where parent = %s and parentfield = 'leave_approvers'""", (d), as_dict=True)])
|
|
||||||
|
|
||||||
return approvers
|
|
||||||
|
|
||||||
def get_total_allocated_leaves(employee, leave_type, from_date, to_date):
|
|
||||||
''' Returns leave allocation between from date and to date '''
|
|
||||||
leave_allocation_records = frappe.db.get_all('Leave Ledger Entry', filters={
|
|
||||||
'docstatus': 1,
|
|
||||||
'is_expired': 0,
|
|
||||||
'leave_type': leave_type,
|
|
||||||
'employee': employee,
|
|
||||||
'transaction_type': 'Leave Allocation'
|
|
||||||
}, or_filters={
|
|
||||||
'from_date': ['between', (from_date, to_date)],
|
|
||||||
'to_date': ['between', (from_date, to_date)]
|
|
||||||
}, fields=['SUM(leaves) as leaves'])
|
|
||||||
|
|
||||||
return flt(leave_allocation_records[0].get('leaves')) if leave_allocation_records else flt(0)
|
|
@ -4,6 +4,20 @@
|
|||||||
|
|
||||||
frappe.query_reports['Employee Leave Balance Summary'] = {
|
frappe.query_reports['Employee Leave Balance Summary'] = {
|
||||||
filters: [
|
filters: [
|
||||||
|
{
|
||||||
|
fieldname:'from_date',
|
||||||
|
label: __('From Date'),
|
||||||
|
fieldtype: 'Date',
|
||||||
|
reqd: 1,
|
||||||
|
default: frappe.defaults.get_default('year_start_date')
|
||||||
|
},
|
||||||
|
{
|
||||||
|
fieldname:'to_date',
|
||||||
|
label: __('To Date'),
|
||||||
|
fieldtype: 'Date',
|
||||||
|
reqd: 1,
|
||||||
|
default: frappe.defaults.get_default('year_end_date')
|
||||||
|
},
|
||||||
{
|
{
|
||||||
fieldname:'company',
|
fieldname:'company',
|
||||||
label: __('Company'),
|
label: __('Company'),
|
||||||
@ -19,18 +33,10 @@ frappe.query_reports['Employee Leave Balance Summary'] = {
|
|||||||
options: 'Employee',
|
options: 'Employee',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
fieldname:'from_date',
|
fieldname:'department',
|
||||||
label: __('From Date'),
|
label: __('Department'),
|
||||||
fieldtype: 'Date',
|
fieldtype: 'Link',
|
||||||
reqd: 1,
|
options: 'Department',
|
||||||
default: frappe.defaults.get_default('year_start_date')
|
|
||||||
},
|
|
||||||
{
|
|
||||||
fieldname:'to_date',
|
|
||||||
label: __('To Date'),
|
|
||||||
fieldtype: 'Date',
|
|
||||||
reqd: 1,
|
|
||||||
default: frappe.defaults.get_default('year_end_date')
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
};
|
};
|
||||||
|
@ -5,9 +5,7 @@ from __future__ import unicode_literals
|
|||||||
import frappe
|
import frappe
|
||||||
from frappe.utils import flt
|
from frappe.utils import flt
|
||||||
from frappe import _
|
from frappe import _
|
||||||
from erpnext.hr.doctype.leave_application.leave_application import get_leaves_for_period
|
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 get_total_allocated_leaves
|
|
||||||
|
|
||||||
def execute(filters=None):
|
def execute(filters=None):
|
||||||
if filters.to_date <= filters.from_date:
|
if filters.to_date <= filters.from_date:
|
||||||
@ -58,16 +56,14 @@ def get_columns():
|
|||||||
def get_data(filters):
|
def get_data(filters):
|
||||||
leave_types = frappe.db.sql_list("SELECT `name` FROM `tabLeave Type` ORDER BY `name` ASC")
|
leave_types = frappe.db.sql_list("SELECT `name` FROM `tabLeave Type` ORDER BY `name` ASC")
|
||||||
|
|
||||||
conditions = {
|
conditions = get_conditions(filters)
|
||||||
'status': 'Active',
|
|
||||||
}
|
|
||||||
|
|
||||||
if filters.get('employee'):
|
user = frappe.session.user
|
||||||
conditions['name'] = filters.get('employee')
|
department_approver_map = get_department_leave_approver_map(filters.get('department'))
|
||||||
|
|
||||||
active_employees = frappe.get_all('Employee',
|
active_employees = frappe.get_list('Employee',
|
||||||
filters=conditions,
|
filters=conditions,
|
||||||
fields=['name', 'employee_name', 'department', 'user_id'])
|
fields=['name', 'employee_name', 'department', 'user_id', 'leave_approver'])
|
||||||
|
|
||||||
data = []
|
data = []
|
||||||
|
|
||||||
@ -76,21 +72,59 @@ def get_data(filters):
|
|||||||
'leave_type': leave_type
|
'leave_type': leave_type
|
||||||
})
|
})
|
||||||
for employee in active_employees:
|
for employee in active_employees:
|
||||||
row = frappe._dict({
|
|
||||||
'employee': employee.name,
|
leave_approvers = department_approver_map.get(employee.department_name, []).append(employee.leave_approver)
|
||||||
'employee_name': employee.employee_name
|
|
||||||
})
|
|
||||||
|
|
||||||
leaves_taken = get_leaves_for_period(employee.name, leave_type,
|
if (len(leave_approvers) and user in leave_approvers) or (user in ["Administrator", employee.user_id]) \
|
||||||
filters.from_date, filters.to_date) * -1
|
or ("HR Manager" in frappe.get_roles(user)):
|
||||||
|
row = frappe._dict({
|
||||||
|
'employee': employee.name,
|
||||||
|
'employee_name': employee.employee_name
|
||||||
|
})
|
||||||
|
|
||||||
opening = get_total_allocated_leaves(employee.name, leave_type, filters.from_date, filters.to_date)
|
leaves_taken = get_leaves_for_period(employee.name, leave_type,
|
||||||
closing = flt(opening) - flt(leaves_taken)
|
filters.from_date, filters.to_date) * -1
|
||||||
|
|
||||||
row.opening_balance = opening
|
opening = get_leave_balance_on(employee.name, leave_type, filters.from_date)
|
||||||
row.leaves_taken = leaves_taken
|
closing = get_leave_balance_on(employee.name, leave_type, filters.to_date)
|
||||||
row.closing_balance = closing
|
|
||||||
row.indent = 1
|
row.opening_balance = opening
|
||||||
data.append(row)
|
row.leaves_taken = leaves_taken
|
||||||
|
row.closing_balance = closing
|
||||||
|
row.indent = 1
|
||||||
|
data.append(row)
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
def get_conditions(filters):
|
||||||
|
conditions={
|
||||||
|
'status': 'Active',
|
||||||
|
}
|
||||||
|
if filters.get('employee'):
|
||||||
|
conditions['name'] = filters.get('employee')
|
||||||
|
|
||||||
|
if filters.get('employee'):
|
||||||
|
conditions['name'] = filters.get('employee')
|
||||||
|
|
||||||
|
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
|
||||||
|
Loading…
x
Reference in New Issue
Block a user