From 2417c93d0eaff061cff7416d7f5f27ace72ecfeb Mon Sep 17 00:00:00 2001 From: Mangesh-Khairnar Date: Mon, 27 May 2019 03:20:10 +0530 Subject: [PATCH] feat: create expiry and carry forward calculation on leave allocation creation --- .../leave_allocation/leave_allocation.js | 2 +- .../leave_allocation/leave_allocation.py | 63 +++++++++++-------- 2 files changed, 38 insertions(+), 27 deletions(-) diff --git a/erpnext/hr/doctype/leave_allocation/leave_allocation.js b/erpnext/hr/doctype/leave_allocation/leave_allocation.js index 228b5528de8..1fc1d896358 100755 --- a/erpnext/hr/doctype/leave_allocation/leave_allocation.js +++ b/erpnext/hr/doctype/leave_allocation/leave_allocation.js @@ -66,4 +66,4 @@ frappe.ui.form.on("Leave Allocation", { 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 8429ad4308a..6fe8fdff243 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 @@ class LeaveAllocation(Document): .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 @@ class LeaveAllocation(Document): 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 @@ class LeaveAllocation(Document): 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 @@ class LeaveAllocation(Document): 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 @@ def get_leave_allocation_for_period(employee, leave_type, from_date, to_date): @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