feat: pro-rata leave allocation
diff --git a/erpnext/hr/doctype/leave_application/leave_application.py b/erpnext/hr/doctype/leave_application/leave_application.py
index 36a4145..2e43721 100755
--- a/erpnext/hr/doctype/leave_application/leave_application.py
+++ b/erpnext/hr/doctype/leave_application/leave_application.py
@@ -515,7 +515,7 @@
 
 		return remaining_leaves
 
-	if expiry:
+	if expiry and allocation.carry_forwarded_leaves:
 		remaining_leaves = _get_remaining_leaves(allocation.carry_forwarded_leaves, expiry)
 
 		return flt(allocation.new_leaves_allocated) + flt(remaining_leaves)
diff --git a/erpnext/hr/doctype/leave_period/leave_period.js b/erpnext/hr/doctype/leave_period/leave_period.js
index b8c5f71..bad2b87 100644
--- a/erpnext/hr/doctype/leave_period/leave_period.js
+++ b/erpnext/hr/doctype/leave_period/leave_period.js
@@ -68,7 +68,7 @@
 				},
 				{
 					"label": "Add unused leaves from previous allocations",
-					"fieldname": "carry_forward_leaves",
+					"fieldname": "carry_forward",
 					"fieldtype": "Check"
 				}
 			],
diff --git a/erpnext/hr/doctype/leave_period/leave_period.py b/erpnext/hr/doctype/leave_period/leave_period.py
index f37efeb..7b0f882 100644
--- a/erpnext/hr/doctype/leave_period/leave_period.py
+++ b/erpnext/hr/doctype/leave_period/leave_period.py
@@ -5,7 +5,7 @@
 from __future__ import unicode_literals
 import frappe
 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 erpnext.hr.utils import validate_overlap, get_employee_leave_policy
 from erpnext.hr.doctype.leave_allocation.leave_allocation import get_carry_forwarded_leaves
@@ -22,8 +22,8 @@
 
 		condition_str = " and " + " and ".join(conditions) if len(conditions) else ""
 
-		employees = frappe.db.sql_list("select name from tabEmployee where status='Active' {condition}"
-			.format(condition=condition_str), tuple(values))
+		employees = frappe._dict(frappe.db.sql("select name, date_of_joining from tabEmployee where status='Active' {condition}"
+			.format(condition=condition_str), tuple(values)))
 
 		return employees
 
@@ -37,29 +37,29 @@
 
 
 	def grant_leave_allocation(self, grade=None, department=None, designation=None,
-			employee=None, carry_forward_leaves=0):
-		employees = self.get_employees({
+			employee=None, carry_forward=0):
+		employee_records = self.get_employees({
 			"grade": grade,
 			"department": department,
 			"designation": designation,
 			"name": employee
 		})
 
-		if employees:
-			if len(employees) > 20:
+		if employee_records:
+			if len(employee_records) > 20:
 				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:
-				grant_leave_alloc_for_employees(employees, self, carry_forward_leaves)
+				grant_leave_alloc_for_employees(employee_records, self, carry_forward)
 		else:
 			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 = []
-	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()
 	count = 0
-	for employee in employees:
+	for employee in employee_records.keys():
 		if employee in existing_allocations_for:
 			continue
 		count +=1
@@ -68,10 +68,10 @@
 			for leave_policy_detail in leave_policy.leave_policy_details:
 				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_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)
 		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:
 		frappe.msgprint(_("Leaves has been granted sucessfully"))
@@ -100,21 +100,30 @@
 		leave_type_details.setdefault(d.name, d)
 	return leave_type_details
 
-def create_leave_allocation(employee, leave_type, new_leaves_allocated, leave_type_details, leave_period, carry_forward_leaves):
-	allocation = frappe.new_doc("Leave Allocation")
-	allocation.employee = employee
-	allocation.leave_type = leave_type
-	allocation.from_date = leave_period.from_date
-	allocation.to_date = leave_period.to_date
+def create_leave_allocation(employee, leave_type, new_leaves_allocated, leave_type_details, leave_period, carry_forward, date_of_joining):
+	''' Creates leave allocation for the given employee in the provided leave period '''
+	if carry_forward and not leave_type_details.get(leave_type).is_carry_forward:
+		carry_forward = 0
+
+	# 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
 	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
 
-	allocation.new_leaves_allocated = new_leaves_allocated
-	allocation.leave_period = leave_period.name
-	if carry_forward_leaves:
-		if leave_type_details.get(leave_type).is_carry_forward:
-			allocation.carry_forward = carry_forward_leaves
+	allocation = frappe.get_doc(dict(
+		doctype="Leave Allocation",
+		employee=employee,
+		leave_type=leave_type,
+		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.submit()
 	return allocation.name
\ No newline at end of file