feat: set carry forwarded leave allocation

This commit is contained in:
Mangesh-Khairnar
2019-04-11 00:22:11 +05:30
parent c28d2e4b2a
commit e46d3a87ea
2 changed files with 75 additions and 146 deletions

View File

@@ -325,7 +325,7 @@
"bold": 1, "bold": 1,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "eval: doc.is_carry_forward != 1", "depends_on": "eval: doc.carry_forward != 1",
"fetch_if_empty": 0, "fetch_if_empty": 0,
"fieldname": "new_leaves_allocated", "fieldname": "new_leaves_allocated",
"fieldtype": "Float", "fieldtype": "Float",
@@ -351,73 +351,6 @@
"translatable": 0, "translatable": 0,
"unique": 0 "unique": 0
}, },
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "eval: doc.is_carry_forward == 1",
"fetch_if_empty": 0,
"fieldname": "old_leaves_allocated",
"fieldtype": "Int",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Old Leaves Allocated",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"fetch_if_empty": 0,
"fieldname": "is_carry_forward",
"fieldtype": "Check",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "is carry forward",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"precision": "",
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 0,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_in_quick_entry": 0, "allow_in_quick_entry": 0,
@@ -437,7 +370,7 @@
"in_global_search": 0, "in_global_search": 0,
"in_list_view": 0, "in_list_view": 0,
"in_standard_filter": 0, "in_standard_filter": 0,
"label": "Add unused leaves from previous allocations", "label": "Allocate unused leaves from previous allocations",
"length": 0, "length": 0,
"no_copy": 0, "no_copy": 0,
"permlevel": 0, "permlevel": 0,
@@ -452,39 +385,6 @@
"translatable": 0, "translatable": 0,
"unique": 0 "unique": 0
}, },
{
"allow_bulk_edit": 0,
"allow_in_quick_entry": 0,
"allow_on_submit": 0,
"bold": 0,
"collapsible": 0,
"columns": 0,
"depends_on": "carry_forward",
"fetch_if_empty": 0,
"fieldname": "carry_forwarded_leaves",
"fieldtype": "Float",
"hidden": 0,
"ignore_user_permissions": 0,
"ignore_xss_filter": 0,
"in_filter": 0,
"in_global_search": 0,
"in_list_view": 0,
"in_standard_filter": 0,
"label": "Unused leaves",
"length": 0,
"no_copy": 0,
"permlevel": 0,
"print_hide": 0,
"print_hide_if_no_value": 0,
"read_only": 1,
"remember_last_selected_value": 0,
"report_hide": 0,
"reqd": 0,
"search_index": 0,
"set_only_once": 0,
"translatable": 0,
"unique": 0
},
{ {
"allow_bulk_edit": 0, "allow_bulk_edit": 0,
"allow_in_quick_entry": 0, "allow_in_quick_entry": 0,
@@ -492,6 +392,7 @@
"bold": 0, "bold": 0,
"collapsible": 0, "collapsible": 0,
"columns": 0, "columns": 0,
"depends_on": "",
"fetch_if_empty": 0, "fetch_if_empty": 0,
"fieldname": "total_leaves_allocated", "fieldname": "total_leaves_allocated",
"fieldtype": "Float", "fieldtype": "Float",
@@ -764,7 +665,7 @@
"issingle": 0, "issingle": 0,
"istable": 0, "istable": 0,
"max_attachments": 0, "max_attachments": 0,
"modified": "2019-04-04 15:09:33.421008", "modified": "2019-04-05 15:31:04.627015",
"modified_by": "Administrator", "modified_by": "Administrator",
"module": "HR", "module": "HR",
"name": "Leave Allocation", "name": "Leave Allocation",

View File

@@ -18,14 +18,19 @@ class ValueMultiplierError(frappe.ValidationError): pass
class LeaveAllocation(Document): class LeaveAllocation(Document):
def validate(self): def validate(self):
self.validate_period() self.validate_period()
self.validate_new_leaves_allocated_value() self.validate_lwp()
self.validate_allocation_overlap() self.validate_allocation_overlap()
self.validate_back_dated_allocation() self.validate_back_dated_allocation()
if not self.carry_forward:
self.validate_new_leaves_allocated_value()
self.validate_leave_allocation_days()
self.set_total_leaves_allocated() self.set_total_leaves_allocated()
self.validate_total_leaves_allocated() self.validate_total_leaves_allocated()
self.validate_lwp()
set_employee_name(self) set_employee_name(self)
self.validate_leave_allocation_days()
def on_update(self):
if self.carry_forward:
self.set_carry_forward_leaves()
def validate_leave_allocation_days(self): def validate_leave_allocation_days(self):
company = frappe.db.get_value("Employee", self.employee, "company") company = frappe.db.get_value("Employee", self.employee, "company")
@@ -44,7 +49,6 @@ class LeaveAllocation(Document):
self.validate_new_leaves_allocated_value() self.validate_new_leaves_allocated_value()
self.set_total_leaves_allocated() self.set_total_leaves_allocated()
frappe.db.set(self,'carry_forwarded_leaves', flt(self.carry_forwarded_leaves))
frappe.db.set(self,'total_leaves_allocated',flt(self.total_leaves_allocated)) frappe.db.set(self,'total_leaves_allocated',flt(self.total_leaves_allocated))
self.validate_against_leave_applications() self.validate_against_leave_applications()
@@ -62,7 +66,7 @@ class LeaveAllocation(Document):
if flt(self.new_leaves_allocated) % 0.5: if flt(self.new_leaves_allocated) % 0.5:
frappe.throw(_("Leaves must be allocated in multiples of 0.5"), ValueMultiplierError) frappe.throw(_("Leaves must be allocated in multiples of 0.5"), ValueMultiplierError)
def validate_allocation_overlap(self, carry_forward=0): def validate_allocation_overlap(self):
leave_allocation = frappe.db.sql(""" leave_allocation = frappe.db.sql("""
SELECT SELECT
name name
@@ -71,10 +75,10 @@ class LeaveAllocation(Document):
employee=%s employee=%s
AND leave_type=%s AND leave_type=%s
AND docstatus=1 AND docstatus=1
AND is_carry_forward={0} AND carry_forward={0}
AND to_date >= %s AND to_date >= %s
AND from_date <= %s""".format(carry_forward), AND from_date <= %s""" #nosec
(self.employee, self.leave_type, self.from_date, self.to_date)) .format(self.carry_forward), (self.employee, self.leave_type, self.from_date, self.to_date))
if leave_allocation: if leave_allocation:
frappe.msgprint(_("{0} already allocated for Employee {1} for period {2} to {3}") frappe.msgprint(_("{0} already allocated for Employee {1} for period {2} to {3}")
@@ -94,12 +98,11 @@ class LeaveAllocation(Document):
BackDatedAllocationError) BackDatedAllocationError)
def set_total_leaves_allocated(self): def set_total_leaves_allocated(self):
self.carry_forwarded_leaves = get_carry_forwarded_leaves(self.employee,
self.leave_type, self.from_date, self.carry_forward)
self.total_leaves_allocated = flt(self.carry_forwarded_leaves) + flt(self.new_leaves_allocated) self.total_leaves_allocated = flt(self.new_leaves_allocated)
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"): 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))) frappe.throw(_("Total leaves allocated is mandatory for Leave Type {0}".format(self.leave_type)))
def validate_total_leaves_allocated(self): def validate_total_leaves_allocated(self):
@@ -119,20 +122,44 @@ class LeaveAllocation(Document):
frappe.throw(_("Total allocated leaves {0} cannot be less than already approved leaves {1} for the period").format(self.total_leaves_allocated, leaves_taken), LessAllocationError) frappe.throw(_("Total allocated leaves {0} cannot be less than already approved leaves {1} for the period").format(self.total_leaves_allocated, leaves_taken), LessAllocationError)
def set_carry_forward_leaves(self): def set_carry_forward_leaves(self):
self.validate_allocation_overlap(carry_forward=1)
self.old_leaves_allocated = get_carry_forwarded_leaves(self.employee, self.leave_type, leaves_allocated
self.from_date, self.is_carry_forward) # check number of days to expire, ignore expiry for default value
expiry_days = frappe.db.get_value("Leave Type",
filters={"leave_type": leave_type, "is_carry_forward": 1},
fieldname="carry_forward_leave_expiry")
max_leaves_allowed = frappe.db.get_value("Leave Type", self.leave_type, "max_leaves_allowed")
leave_period = get_leave_period(self.from_date, self.to_date, company)
if leave_period:
leave_allocated = get_leave_allocation_for_period(self.employee, self.leave_type, leave_period[0].from_date, leave_period[0].to_date)
carry_forwarded_leaves = get_carry_forwarded_leaves(self.employee, self.leave_type,
self.from_date, expiry_days)
leaves_allocated += carry_forwarded_leaves
if leaves_allocated > max_leaves_allowed:
self.total_leaves_allocated = max_leaves_allowed - leaves_allocated
else:
self.total_leaves_allocated = carry_forwarded_leaves
def get_leave_allocation_for_period(employee, leave_type, from_date, to_date): def get_leave_allocation_for_period(employee, leave_type, from_date, to_date):
leave_allocated = 0 leave_allocated = 0
leave_allocations = frappe.db.sql(""" leave_allocations = frappe.db.sql("""
select employee, leave_type, from_date, to_date, total_leaves_allocated SELECT
from `tabLeave Allocation` employee,
where employee=%(employee)s and leave_type=%(leave_type)s leave_type,
and docstatus=1 from_date,
and (from_date between %(from_date)s and %(to_date)s to_date,
or to_date between %(from_date)s and %(to_date)s total_leaves_allocated
or (from_date < %(from_date)s and to_date > %(to_date)s)) FROM `tabLeave Allocation`
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, "from_date": from_date,
"to_date": to_date, "to_date": to_date,
@@ -147,31 +174,32 @@ def get_leave_allocation_for_period(employee, leave_type, from_date, to_date):
return leave_allocated return leave_allocated
@frappe.whitelist() @frappe.whitelist()
def get_carry_forwarded_leaves(employee, leave_type, date, is_carry_forward=None): def get_carry_forwarded_leaves(employee, leave_type, date, expiry_days):
carry_forwarded_leaves = 0 carry_forwarded_leaves = 0
if is_carry_forward: validate_carry_forward(leave_type)
validate_carry_forward(leave_type) filters = {
"employee": employee,
"leave_type": leave_type,
"docstatus": 1,
"to_date": ("<", date)
}
limit = 1
if expiry_days:
filters.update(carry_forward=0)
limit = 2
previous_allocation = frappe.db.sql(""" previous_allocation = frappe.get_all("Leave Allocation",
SELECT filters=filters,
name, fields=["name","from_date","to_date","total_leaves_allocated"],
from_date, order_by="to_date desc",
to_date, limit=limit)
total_leaves_allocated
FROM `tabLeave Allocation`
WHERE
employee=%s
AND leave_type=%s
AND docstatus=1
AND to_date < %s
ORDER BY to_date desc limit 1
""", (employee, leave_type, date), as_dict=1)
if previous_allocation:
leaves_taken = get_approved_leaves_for_period(employee, leave_type,
previous_allocation[0].from_date, previous_allocation[0].to_date)
carry_forwarded_leaves = flt(previous_allocation[0].total_leaves_allocated) - flt(leaves_taken) if previous_allocation:
leaves_taken = get_approved_leaves_for_period(employee, leave_type,
previous_allocation[0].from_date, previous_allocation[0].to_date)
carry_forwarded_leaves = flt(previous_allocation[0].total_leaves_allocated) - flt(leaves_taken)
return carry_forwarded_leaves return carry_forwarded_leaves