feat: create expiry and carry forward calculation on leave allocation creation
diff --git a/erpnext/hr/doctype/leave_allocation/leave_allocation.js b/erpnext/hr/doctype/leave_allocation/leave_allocation.js
index 228b552..1fc1d89 100755
--- a/erpnext/hr/doctype/leave_allocation/leave_allocation.js
+++ b/erpnext/hr/doctype/leave_allocation/leave_allocation.js
@@ -66,4 +66,4 @@
frm.set_value("total_leaves_allocated", flt(frm.doc.new_leaves_allocated));
}
}
-})
\ No newline at end of file
+});
\ No newline at end of file
diff --git a/erpnext/hr/doctype/leave_allocation/leave_allocation.py b/erpnext/hr/doctype/leave_allocation/leave_allocation.py
index 8429ad4..6fe8fdf 100755
--- a/erpnext/hr/doctype/leave_allocation/leave_allocation.py
+++ b/erpnext/hr/doctype/leave_allocation/leave_allocation.py
@@ -3,7 +3,7 @@
from __future__ import unicode_literals
import frappe
-from frappe.utils import flt, date_diff, formatdate
+from frappe.utils import flt, date_diff, formatdate, add_days
from frappe import _
from frappe.model.document import Document
from erpnext.hr.utils import set_employee_name, get_leave_period
@@ -42,6 +42,7 @@
.format(self.leave_type, self.employee))
def on_submit(self):
+ self.expire_previous_allocation()
self.create_leave_ledger_entry()
def on_cancel(self):
@@ -89,10 +90,20 @@
self.leave_type, self.from_date, self.carry_forward)
self.total_leaves_allocated = flt(self.carry_forwarded_leaves) + flt(self.new_leaves_allocated)
+ self.maintain_carry_forwarded_leaves()
if not self.total_leaves_allocated and not frappe.db.get_value("Leave Type", self.leave_type, "is_earned_leave") and not frappe.db.get_value("Leave Type", self.leave_type, "is_compensatory"):
frappe.throw(_("Total leaves allocated is mandatory for Leave Type {0}".format(self.leave_type)))
+ def maintain_carry_forwarded_leaves(self):
+ ''' reduce the carry forwarded leaves to be within the maximum allowed leaves '''
+ if not self.carry_forward:
+ return
+ max_leaves_allowed = frappe.db.get_value("Leave Type", self.leave_type, "max_leaves_allowed")
+ if self.new_leaves_allocated <= max_leaves_allowed <= self.total_leaves_allocated:
+ self.carry_forwarded_leaves = max_leaves_allowed - flt(self.new_leaves_allocated)
+ self.total_leaves_allocated = flt(max_leaves_allowed)
+
def validate_total_leaves_allocated(self):
# Adding a day to include To Date in the difference
date_difference = date_diff(self.to_date, self.from_date) + 1
@@ -102,9 +113,9 @@
def create_leave_ledger_entry(self, submit=True):
if self.carry_forwarded_leaves:
expiry_days = frappe.db.get_value("Leave Type", self.leave_type, "carry_forward_leave_expiry")
-
args = dict(
leaves=self.carry_forwarded_leaves,
+ from_date=self.from_date,
to_date=add_days(self.from_date, expiry_days) if expiry_days else self.to_date,
is_carry_forward=1
)
@@ -112,11 +123,26 @@
args = dict(
leaves=self.new_leaves_allocated,
+ from_date=self.from_date,
to_date=self.to_date,
is_carry_forward=0
)
create_leave_ledger_entry(self, args, submit)
+ def expire_previous_allocation(self):
+ ''' expire previous allocation leaves '''
+ leaves = get_remaining_leaves(self.employee, self.leave_type, self.from_date)
+
+ if flt(leaves) > 0:
+ args = dict(
+ leaves=leaves * -1,
+ from_date=self.to_date,
+ to_date=self.to_date,
+ is_carry_forward=0,
+ is_expired=1
+ )
+ create_leave_ledger_entry(self, args)
+
def get_leave_allocation_for_period(employee, leave_type, from_date, to_date):
leave_allocated = 0
leave_allocations = frappe.db.sql("""
@@ -143,35 +169,20 @@
@frappe.whitelist()
def get_carry_forwarded_leaves(employee, leave_type, date, carry_forward=None):
carry_forwarded_leaves = 0
-
if carry_forward:
validate_carry_forward(leave_type)
-
- carry_forwarded_leaves = frappe.db.sql("""
- SELECT
- SUM(leaves)
- FROM `tabLeave Ledger Entry`
- WHERE
- employee=%s
- AND leave_type=%s
- AND docstatus=1
- AND to_date < %s
- AND name NOT IN (
- SELECT name
- from `tabLeave Ledger Entry`
- WHERE
- employee=%s
- AND leave_type=%s
- AND docstatus=1
- AND to_date < %s
- is_expired=1
- ORDER BY creation DESC
- )
- ORDER BY creation DESC
- """, (employee, leave_type, date), as_dict=1)
+ carry_forwarded_leaves = get_remaining_leaves(employee, leave_type, date)
return carry_forwarded_leaves
+def get_remaining_leaves(employee, leave_type, date):
+ return frappe.db.get_value("Leave Ledger Entry", filters={
+ "to_date": ("<=", date),
+ "employee": employee,
+ "docstatus": 1,
+ "leave_type": leave_type,
+ }, fieldname=['SUM(leaves)'])
+
def validate_carry_forward(leave_type):
if not frappe.db.get_value("Leave Type", leave_type, "is_carry_forward"):
frappe.throw(_("Leave Type {0} cannot be carry-forwarded").format(leave_type))
\ No newline at end of file