feat: validate leave allocation period to be within expiry limits
diff --git a/erpnext/hr/doctype/leave_allocation/leave_allocation.py b/erpnext/hr/doctype/leave_allocation/leave_allocation.py
index 7f8f806..0c00aff 100755
--- a/erpnext/hr/doctype/leave_allocation/leave_allocation.py
+++ b/erpnext/hr/doctype/leave_allocation/leave_allocation.py
@@ -44,9 +44,17 @@
 		self.validate_against_leave_applications()
 
 	def validate_period(self):
-		if date_diff(self.to_date, self.from_date) <= 0:
+		allocation_period = date_diff(self.to_date, self.from_date)
+
+		if allocation_period <= 0:
 			frappe.throw(_("To date cannot be before from date"))
 
+		# check if the allocation period is more than the expiry allows for carry forwarded allocation
+		if self.carry_forward:
+			expiry_days = get_days_to_expiry_for_leave_type(self.leave_type)
+			if allocation_period > expiry_days:
+				frappe.throw(_("Leave allocation period cannot be more than the expiry days allocated"))
+
 	def validate_lwp(self):
 		if frappe.db.get_value("Leave Type", self.leave_type, "is_lwp"):
 			frappe.throw(_("Leave Type {0} cannot be allocated since it is leave without pay").format(self.leave_type))
@@ -115,13 +123,10 @@
 				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_forwarded_leaves(self):
-		# check number of days to expire, ignore expiry for default value 0
-		expiry_days = frappe.db.get_value("Leave Type",
-			filters={"leave_type": leave_type, "is_carry_forward": 1},
-			fieldname="carry_forward_leave_expiry")
+		self.carry_forwarded_leaves = get_carry_forwarded_leaves(self.employee, self.leave_type, self.from_date)
 
-		self.carry_forwarded_leaves = get_carry_forwarded_leaves(self.employee, self.leave_type, self.from_date, expiry_days)
 		max_leaves, leaves_allocated = self.get_max_leaves_with_leaves_allocated_for_leave_type(self.carry_forwarded_leaves)
+
 		if leaves_allocated > max_leaves:
 			self.carry_forwarded_leaves = max_leaves - (leaves_allocated - self.carry_forwarded_leaves)
 
@@ -168,9 +173,10 @@
 	return leave_allocated
 
 @frappe.whitelist()
-def get_carry_forwarded_leaves(employee, leave_type, date, expiry_days):
+def get_carry_forwarded_leaves(employee, leave_type, date):
+	''' Calculates carry forwarded days based on previous unused leave allocations '''
 	carry_forwarded_leaves = 0
-
+	expiry_days = get_days_to_expiry_for_leave_type(leave_type)
 	validate_carry_forward(leave_type)
 	filters = {
 		"employee": employee,
@@ -179,6 +185,8 @@
 		"to_date": ("<", date)
 	}
 	limit = 1
+
+	# check number of days to expire, ignore expiry for default value 0
 	if expiry_days:
 		filters.update(carry_forward=0)
 		limit = 2
@@ -197,6 +205,14 @@
 
 	return carry_forwarded_leaves
 
+def get_days_to_expiry_for_leave_type(leave_type):
+	''' returns days to expiry for a provided leave type '''
+	expiry_days = frappe.db.get_value("Leave Type",
+		filters={"leave_type": leave_type, "is_carry_forward": 1},
+		fieldname="carry_forward_leave_expiry")
+
+
+
 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
diff --git a/erpnext/hr/doctype/leave_period/leave_period.py b/erpnext/hr/doctype/leave_period/leave_period.py
index 1e2884d..0c83a1e 100644
--- a/erpnext/hr/doctype/leave_period/leave_period.py
+++ b/erpnext/hr/doctype/leave_period/leave_period.py
@@ -127,6 +127,6 @@
 	allocation.to_date = add_days(leave_period.from_date, leave_type_details.carry_forward_leave_expiry) if not leave_type_details.carry_forward_leave_expiry else leave_period.to_date
 	allocation.leave_period = leave_period.name
 	allocation.carry_forward = carry_forward_leaves
-	allocation.carry_forwarded_leaves = get_carry_forwarded_leaves(employee, leave_type, leave_period.from_date, leave_type_details.carry_forward_leave_expiry)
+	allocation.carry_forwarded_leaves = get_carry_forwarded_leaves(employee, leave_type, leave_period.from_date)
 	allocation.save(ignore_permissions=True)
 	allocation.submit()
\ No newline at end of file