Hi Prashant,
Thank you so much for reply.
So, Below is the Native Code by Frappe.
It allocated the 2.5 Earned Leaves to every employee every month.
But at the last of November, it gave the earned leaves to some employees and not to some employees
I don’t know why, it did that.
and I am not able to find the pattern of the employees who got 2.5 earned leaves & those who did not.
I also cannot check one by one the emplooyees as there are 600+ employees.
def allocate_earned_leaves():
"""Allocate earned leaves to Employees"""
e_leave_types = get_earned_leaves()
today = getdate()
for e_leave_type in e_leave_types:
leave_allocations = get_leave_allocations(today, e_leave_type.name)
for allocation in leave_allocations:
if not allocation.leave_policy_assignment and not allocation.leave_policy:
continue
leave_policy = (
allocation.leave_policy
if allocation.leave_policy
else frappe.db.get_value(
"Leave Policy Assignment", allocation.leave_policy_assignment, ["leave_policy"]
)
)
annual_allocation = frappe.db.get_value(
"Leave Policy Detail",
filters={"parent": leave_policy, "leave_type": e_leave_type.name},
fieldname=["annual_allocation"],
)
from_date = allocation.from_date
if e_leave_type.based_on_date_of_joining:
from_date = frappe.db.get_value("Employee", allocation.employee, "date_of_joining")
if check_effective_date(
from_date, today, e_leave_type.earned_leave_frequency, e_leave_type.based_on_date_of_joining
):
update_previous_leave_allocation(allocation, annual_allocation, e_leave_type)
def update_previous_leave_allocation(allocation, annual_allocation, e_leave_type):
earned_leaves = get_monthly_earned_leave(
annual_allocation, e_leave_type.earned_leave_frequency, e_leave_type.rounding
)
allocation = frappe.get_doc("Leave Allocation", allocation.name)
new_allocation = flt(allocation.total_leaves_allocated) + flt(earned_leaves)
if new_allocation > e_leave_type.max_leaves_allowed and e_leave_type.max_leaves_allowed > 0:
new_allocation = e_leave_type.max_leaves_allowed
if new_allocation != allocation.total_leaves_allocated:
today_date = today()
allocation.db_set("total_leaves_allocated", new_allocation, update_modified=False)
create_additional_leave_ledger_entry(allocation, earned_leaves, today_date)
if e_leave_type.based_on_date_of_joining:
text = _("allocated {0} leave(s) via scheduler on {1} based on the date of joining").format(
frappe.bold(earned_leaves), frappe.bold(formatdate(today_date))
)
else:
text = _("allocated {0} leave(s) via scheduler on {1}").format(
frappe.bold(earned_leaves), frappe.bold(formatdate(today_date))
)
allocation.add_comment(comment_type="Info", text=text)
def get_monthly_earned_leave(annual_leaves, frequency, rounding):
earned_leaves = 0.0
divide_by_frequency = {"Yearly": 1, "Half-Yearly": 6, "Quarterly": 4, "Monthly": 12}
if annual_leaves:
earned_leaves = flt(annual_leaves) / divide_by_frequency[frequency]
if rounding:
if rounding == "0.25":
earned_leaves = round(earned_leaves * 4) / 4
elif rounding == "0.5":
earned_leaves = round(earned_leaves * 2) / 2
else:
earned_leaves = round(earned_leaves)
return earned_leaves
def is_earned_leave_already_allocated(allocation, annual_allocation):
from erpnext.hr.doctype.leave_policy_assignment.leave_policy_assignment import (
get_leave_type_details,
)
leave_type_details = get_leave_type_details()
date_of_joining = frappe.db.get_value("Employee", allocation.employee, "date_of_joining")
assignment = frappe.get_doc("Leave Policy Assignment", allocation.leave_policy_assignment)
leaves_for_passed_months = assignment.get_leaves_for_passed_months(
allocation.leave_type, annual_allocation, leave_type_details, date_of_joining
)
# exclude carry-forwarded leaves while checking for leave allocation for passed months
num_allocations = allocation.total_leaves_allocated
if allocation.unused_leaves:
num_allocations -= allocation.unused_leaves
if num_allocations >= leaves_for_passed_months:
return True
return False
def get_leave_allocations(date, leave_type):
return frappe.db.sql(
"""select name, employee, from_date, to_date, leave_policy_assignment, leave_policy
from `tabLeave Allocation`
where
%s between from_date and to_date and docstatus=1
and leave_type=%s""",
(date, leave_type),
as_dict=1,
)
def get_earned_leaves():
return frappe.get_all(
"Leave Type",
fields=[
"name",
"max_leaves_allowed",
"earned_leave_frequency",
"rounding",
"based_on_date_of_joining",
],
filters={"is_earned_leave": 1},
)
def create_additional_leave_ledger_entry(allocation, leaves, date):
"""Create leave ledger entry for leave types"""
allocation.new_leaves_allocated = leaves
allocation.from_date = date
allocation.unused_leaves = 0
allocation.create_leave_ledger_entry()
def check_effective_date(from_date, to_date, frequency, based_on_date_of_joining):
import calendar
from dateutil import relativedelta
from_date = get_datetime(from_date)
to_date = get_datetime(to_date)
rd = relativedelta.relativedelta(to_date, from_date)
# last day of month
last_day = calendar.monthrange(to_date.year, to_date.month)[1]
if (from_date.day == to_date.day and based_on_date_of_joining) or (
not based_on_date_of_joining and to_date.day == last_day
):
if frequency == "Monthly":
return True
elif frequency == "Quarterly" and rd.months % 3:
return True
elif frequency == "Half-Yearly" and rd.months % 6:
return True
elif frequency == "Yearly" and rd.months % 12:
return True
if frappe.flags.in_test:
return True
return False