feat: pro-rata leave allocation

This commit is contained in:
Mangesh-Khairnar 2019-08-05 14:47:37 +05:30
parent f281f00d43
commit 6bed870dfa
3 changed files with 36 additions and 27 deletions

View File

@ -515,7 +515,7 @@ def get_remaining_leaves(allocation, leaves_taken, date, expiry):
return remaining_leaves return remaining_leaves
if expiry: if expiry and allocation.carry_forwarded_leaves:
remaining_leaves = _get_remaining_leaves(allocation.carry_forwarded_leaves, expiry) remaining_leaves = _get_remaining_leaves(allocation.carry_forwarded_leaves, expiry)
return flt(allocation.new_leaves_allocated) + flt(remaining_leaves) return flt(allocation.new_leaves_allocated) + flt(remaining_leaves)

View File

@ -68,7 +68,7 @@ frappe.ui.form.on('Leave Period', {
}, },
{ {
"label": "Add unused leaves from previous allocations", "label": "Add unused leaves from previous allocations",
"fieldname": "carry_forward_leaves", "fieldname": "carry_forward",
"fieldtype": "Check" "fieldtype": "Check"
} }
], ],

View File

@ -5,7 +5,7 @@
from __future__ import unicode_literals from __future__ import unicode_literals
import frappe import frappe
from frappe import _ from frappe import _
from frappe.utils import getdate, cstr, add_days from frappe.utils import getdate, cstr, add_days, date_diff, getdate, ceil
from frappe.model.document import Document from frappe.model.document import Document
from erpnext.hr.utils import validate_overlap, get_employee_leave_policy from erpnext.hr.utils import validate_overlap, get_employee_leave_policy
from erpnext.hr.doctype.leave_allocation.leave_allocation import get_carry_forwarded_leaves from erpnext.hr.doctype.leave_allocation.leave_allocation import get_carry_forwarded_leaves
@ -22,8 +22,8 @@ class LeavePeriod(Document):
condition_str = " and " + " and ".join(conditions) if len(conditions) else "" condition_str = " and " + " and ".join(conditions) if len(conditions) else ""
employees = frappe.db.sql_list("select name from tabEmployee where status='Active' {condition}" employees = frappe._dict(frappe.db.sql("select name, date_of_joining from tabEmployee where status='Active' {condition}"
.format(condition=condition_str), tuple(values)) .format(condition=condition_str), tuple(values)))
return employees return employees
@ -37,29 +37,29 @@ class LeavePeriod(Document):
def grant_leave_allocation(self, grade=None, department=None, designation=None, def grant_leave_allocation(self, grade=None, department=None, designation=None,
employee=None, carry_forward_leaves=0): employee=None, carry_forward=0):
employees = self.get_employees({ employee_records = self.get_employees({
"grade": grade, "grade": grade,
"department": department, "department": department,
"designation": designation, "designation": designation,
"name": employee "name": employee
}) })
if employees: if employee_records:
if len(employees) > 20: if len(employee_records) > 20:
frappe.enqueue(grant_leave_alloc_for_employees, timeout=600, frappe.enqueue(grant_leave_alloc_for_employees, timeout=600,
employees=employees, leave_period=self, carry_forward_leaves=carry_forward_leaves) employee_records=employee_records, leave_period=self, carry_forward=carry_forward)
else: else:
grant_leave_alloc_for_employees(employees, self, carry_forward_leaves) grant_leave_alloc_for_employees(employee_records, self, carry_forward)
else: else:
frappe.msgprint(_("No Employee Found")) frappe.msgprint(_("No Employee Found"))
def grant_leave_alloc_for_employees(employees, leave_period, carry_forward_leaves=0): def grant_leave_alloc_for_employees(employee_records, leave_period, carry_forward=0):
leave_allocations = [] leave_allocations = []
existing_allocations_for = get_existing_allocations(employees, leave_period.name) existing_allocations_for = get_existing_allocations(list(employee_records.keys()), leave_period.name)
leave_type_details = get_leave_type_details() leave_type_details = get_leave_type_details()
count = 0 count = 0
for employee in employees: for employee in employee_records.keys():
if employee in existing_allocations_for: if employee in existing_allocations_for:
continue continue
count +=1 count +=1
@ -68,10 +68,10 @@ def grant_leave_alloc_for_employees(employees, leave_period, carry_forward_leave
for leave_policy_detail in leave_policy.leave_policy_details: for leave_policy_detail in leave_policy.leave_policy_details:
if not leave_type_details.get(leave_policy_detail.leave_type).is_lwp: if not leave_type_details.get(leave_policy_detail.leave_type).is_lwp:
leave_allocation = create_leave_allocation(employee, leave_policy_detail.leave_type, leave_allocation = create_leave_allocation(employee, leave_policy_detail.leave_type,
leave_policy_detail.annual_allocation, leave_type_details, leave_period, carry_forward_leaves) leave_policy_detail.annual_allocation, leave_type_details, leave_period, carry_forward, employee_records.get(employee))
leave_allocations.append(leave_allocation) leave_allocations.append(leave_allocation)
frappe.db.commit() frappe.db.commit()
frappe.publish_progress(count*100/len(set(employees) - set(existing_allocations_for)), title = _("Allocating leaves...")) frappe.publish_progress(count*100/len(set(employee_records.keys()) - set(existing_allocations_for)), title = _("Allocating leaves..."))
if leave_allocations: if leave_allocations:
frappe.msgprint(_("Leaves has been granted sucessfully")) frappe.msgprint(_("Leaves has been granted sucessfully"))
@ -100,21 +100,30 @@ def get_leave_type_details():
leave_type_details.setdefault(d.name, d) leave_type_details.setdefault(d.name, d)
return leave_type_details return leave_type_details
def create_leave_allocation(employee, leave_type, new_leaves_allocated, leave_type_details, leave_period, carry_forward_leaves): def create_leave_allocation(employee, leave_type, new_leaves_allocated, leave_type_details, leave_period, carry_forward, date_of_joining):
allocation = frappe.new_doc("Leave Allocation") ''' Creates leave allocation for the given employee in the provided leave period '''
allocation.employee = employee if carry_forward and not leave_type_details.get(leave_type).is_carry_forward:
allocation.leave_type = leave_type carry_forward = 0
allocation.from_date = leave_period.from_date
allocation.to_date = leave_period.to_date # Calculate leaves at pro-rata basis for employees joining after the beginning of the given leave period
if getdate(date_of_joining) > getdate(leave_period.from_date):
remaining_period = ((date_diff(leave_period.to_date, date_of_joining) + 1) / (date_diff(leave_period.to_date, leave_period.from_date) + 1))
new_leaves_allocated = ceil(new_leaves_allocated * remaining_period)
# Earned Leaves and Compensatory Leaves are allocated by scheduler, initially allocate 0 # Earned Leaves and Compensatory Leaves are allocated by scheduler, initially allocate 0
if leave_type_details.get(leave_type).is_earned_leave == 1 or leave_type_details.get(leave_type).is_compensatory == 1: if leave_type_details.get(leave_type).is_earned_leave == 1 or leave_type_details.get(leave_type).is_compensatory == 1:
new_leaves_allocated = 0 new_leaves_allocated = 0
allocation.new_leaves_allocated = new_leaves_allocated allocation = frappe.get_doc(dict(
allocation.leave_period = leave_period.name doctype="Leave Allocation",
if carry_forward_leaves: employee=employee,
if leave_type_details.get(leave_type).is_carry_forward: leave_type=leave_type,
allocation.carry_forward = carry_forward_leaves from_date=leave_period.from_date,
to_date=leave_period.to_date,
new_leaves_allocated=new_leaves_allocated,
leave_period=leave_period.name,
carry_forward=carry_forward
))
allocation.save(ignore_permissions = True) allocation.save(ignore_permissions = True)
allocation.submit() allocation.submit()
return allocation.name return allocation.name