feat: Utility function to get possible loan disbursal amount
diff --git a/erpnext/loan_management/doctype/loan/test_loan.py b/erpnext/loan_management/doctype/loan/test_loan.py
index 23815d598..b75f7bd 100644
--- a/erpnext/loan_management/doctype/loan/test_loan.py
+++ b/erpnext/loan_management/doctype/loan/test_loan.py
@@ -17,6 +17,7 @@
 from erpnext.loan_management.doctype.loan.loan import create_loan_security_unpledge
 from erpnext.loan_management.doctype.loan_security_unpledge.loan_security_unpledge import get_pledged_security_qty
 from erpnext.loan_management.doctype.loan_application.loan_application import create_pledge
+from erpnext.loan_management.doctype.loan_disbursement.loan_disbursement import get_disbursal_amount
 
 class TestLoan(unittest.TestCase):
 	def setUp(self):
@@ -323,6 +324,56 @@
 		self.assertEqual(loan.status, 'Closed')
 		self.assertEquals(sum(pledged_qty.values()), 0)
 
+	def test_disbursal_check_with_shortfall(self):
+		pledges = [{
+			"loan_security": "Test Security 2",
+			"qty": 8000.00,
+			"haircut": 50,
+		}]
+
+		loan_application = create_loan_application('_Test Company', self.applicant2,
+			'Stock Loan', pledges, "Repay Over Number of Periods", 12)
+
+		create_pledge(loan_application)
+
+		loan = create_loan_with_security(self.applicant2, "Stock Loan", "Repay Over Number of Periods", 12, loan_application)
+		loan.submit()
+
+		#Disbursing 7,00,000 from the allowed 10,00,000 according to security pledge
+		make_loan_disbursement_entry(loan.name, 700000)
+
+		frappe.db.sql("""UPDATE `tabLoan Security Price` SET loan_security_price = 100
+			where loan_security='Test Security 2'""")
+
+		create_process_loan_security_shortfall()
+		loan_security_shortfall = frappe.get_doc("Loan Security Shortfall", {"loan": loan.name})
+		self.assertTrue(loan_security_shortfall)
+
+		self.assertEqual(get_disbursal_amount(loan.name), 0)
+
+		frappe.db.sql(""" UPDATE `tabLoan Security Price` SET loan_security_price = 250
+			where loan_security='Test Security 2'""")
+
+	def test_disbursal_check_without_shortfall(self):
+		pledges = [{
+			"loan_security": "Test Security 2",
+			"qty": 8000.00,
+			"haircut": 50,
+		}]
+
+		loan_application = create_loan_application('_Test Company', self.applicant2,
+			'Stock Loan', pledges, "Repay Over Number of Periods", 12)
+
+		create_pledge(loan_application)
+
+		loan = create_loan_with_security(self.applicant2, "Stock Loan", "Repay Over Number of Periods", 12, loan_application)
+		loan.submit()
+
+		#Disbursing 7,00,000 from the allowed 10,00,000 according to security pledge
+		make_loan_disbursement_entry(loan.name, 700000)
+
+		self.assertEqual(get_disbursal_amount(loan.name), 300000)
+
 
 def create_loan_accounts():
 	if not frappe.db.exists("Account", "Loans and Advances (Assets) - _TC"):
diff --git a/erpnext/loan_management/doctype/loan_application/loan_application.js b/erpnext/loan_management/doctype/loan_application/loan_application.js
index b56fce1..1365274 100644
--- a/erpnext/loan_management/doctype/loan_application/loan_application.js
+++ b/erpnext/loan_management/doctype/loan_application/loan_application.js
@@ -33,18 +33,18 @@
 
 			if (frm.doc.is_secured_loan) {
 				frappe.db.get_value("Loan Security Pledge", {"loan_application": frm.doc.name, "docstatus": 1}, "name", (r) => {
-					if (!r) {
+					if (Object.keys(r).length === 0) {
 						frm.add_custom_button(__('Loan Security Pledge'), function() {
-							frm.trigger('create_loan_security_pledge')
+							frm.trigger('create_loan_security_pledge');
 						},__('Create'))
 					}
 				});
 			}
 
 			frappe.db.get_value("Loan", {"loan_application": frm.doc.name, "docstatus": 1}, "name", (r) => {
-				if (!r) {
+				if (Object.keys(r).length === 0) {
 					frm.add_custom_button(__('Loan'), function() {
-						frm.trigger('create_loan')
+						frm.trigger('create_loan');
 					},__('Create'))
 				} else {
 					frm.set_df_property('status', 'read_only', 1);
@@ -54,7 +54,7 @@
 	},
 	create_loan: function(frm) {
 		if (frm.doc.status != "Approved") {
-			frappe.throw(__("Cannot create loan until application is approved"))
+			frappe.throw(__("Cannot create loan until application is approved"));
 		}
 
 		frappe.model.open_mapped_doc({
diff --git a/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py b/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py
index 6c27e12..260fada 100644
--- a/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py
+++ b/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py
@@ -67,28 +67,10 @@
 			disbursed_amount = self.disbursed_amount + loan_details.disbursed_amount
 			total_payment = loan_details.total_payment
 
-			if disbursed_amount > loan_details.loan_amount and loan_details.is_term_loan:
-				frappe.throw(_("Disbursed Amount cannot be greater than loan amount"))
+			possible_disbursal_amount = get_disbursal_amount(self.against_loan)
 
-			if loan_details.status == 'Disbursed':
-				pending_principal_amount = flt(loan_details.total_payment) - flt(loan_details.total_interest_payable) \
-					- flt(loan_details.total_principal_paid)
-			else:
-				pending_principal_amount = loan_details.disbursed_amount
-
-			security_value = 0.0
-			if loan_details.is_secured_loan:
-				security_value = get_total_pledged_security_value(self.against_loan)
-
-			if not security_value:
-				security_value = loan_details.loan_amount
-
-			if pending_principal_amount + self.disbursed_amount > flt(security_value):
-				allowed_amount = security_value - pending_principal_amount
-				if allowed_amount < 0:
-					allowed_amount = 0
-
-				frappe.throw(_("Disbursed Amount cannot be greater than {0}").format(allowed_amount))
+			if self.disbursed_amount > possible_disbursal_amount:
+				frappe.throw(_("Disbursed Amount cannot be greater than {0}").format(possible_disbursal_amount))
 
 			if loan_details.status == "Disbursed" and not loan_details.is_term_loan:
 				process_loan_interest_accrual_for_demand_loans(posting_date=add_days(self.disbursement_date, -1),
@@ -176,3 +158,32 @@
 		security_value += (loan_security_price_map.get(security) * qty * hair_cut_map.get(security))/100
 
 	return security_value
+
+@frappe.whitelist()
+def get_disbursal_amount(loan):
+	loan_details = frappe.get_all("Loan", fields = ["loan_amount", "disbursed_amount", "total_payment",
+		"total_principal_paid", "total_interest_payable", "status", "is_term_loan", "is_secured_loan"],
+		filters= { "name": loan })[0]
+
+	if loan_details.is_secured_loan and frappe.get_all('Loan Security Shortfall', filters={'loan': loan,
+		'status': 'Pending'}):
+		return 0
+
+	if loan_details.status == 'Disbursed':
+		pending_principal_amount = flt(loan_details.total_payment) - flt(loan_details.total_interest_payable) \
+			- flt(loan_details.total_principal_paid)
+	else:
+		pending_principal_amount = flt(loan_details.disbursed_amount)
+
+	security_value = 0.0
+	if loan_details.is_secured_loan:
+		security_value = get_total_pledged_security_value(loan)
+
+	if not security_value and not loan_details.is_secured_loan:
+		security_value = flt(loan_details.loan_amount)
+
+	disbursal_amount = flt(security_value) - flt(pending_principal_amount)
+
+	return disbursal_amount
+
+
diff --git a/erpnext/loan_management/doctype/loan_interest_accrual/loan_interest_accrual.py b/erpnext/loan_management/doctype/loan_interest_accrual/loan_interest_accrual.py
index c5111fd..1d3fa71 100644
--- a/erpnext/loan_management/doctype/loan_interest_accrual/loan_interest_accrual.py
+++ b/erpnext/loan_management/doctype/loan_interest_accrual/loan_interest_accrual.py
@@ -85,8 +85,11 @@
 	if no_of_days <= 0:
 		return
 
-	pending_principal_amount = flt(loan.total_payment) - flt(loan.total_interest_payable) \
-		- flt(loan.total_principal_paid)
+	if loan.status == 'Disbursed':
+		pending_principal_amount = flt(loan.total_payment) - flt(loan.total_interest_payable) \
+			- flt(loan.total_principal_paid)
+	else:
+		pending_principal_amount = loan.disbursed_amount
 
 	interest_per_day = (pending_principal_amount * loan.rate_of_interest) / (days_in_year(get_datetime(posting_date).year) * 100)
 	payable_interest = interest_per_day * no_of_days
@@ -107,7 +110,7 @@
 
 def make_accrual_interest_entry_for_demand_loans(posting_date, process_loan_interest, open_loans=None, loan_type=None):
 	query_filters = {
-		"status": "Disbursed",
+		"status": ('in', ['Disbursed', 'Partially Disbursed']),
 		"docstatus": 1
 	}
 
@@ -118,8 +121,9 @@
 
 	if not open_loans:
 		open_loans = frappe.get_all("Loan",
-			fields=["name", "total_payment", "total_amount_paid", "loan_account", "interest_income_account", "is_term_loan",
-				"disbursement_date", "applicant_type", "applicant", "rate_of_interest", "total_interest_payable", "repayment_start_date"],
+			fields=["name", "total_payment", "total_amount_paid", "loan_account", "interest_income_account",
+				"is_term_loan", "status", "disbursement_date", "disbursed_amount", "applicant_type", "applicant",
+				"rate_of_interest", "total_interest_payable", "total_principal_paid", "repayment_start_date"],
 			filters=query_filters)
 
 	for loan in open_loans:
diff --git a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py
index 9605045..451ae85 100644
--- a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py
+++ b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py
@@ -281,7 +281,7 @@
 
 		due_date = add_days(entry.posting_date, 1)
 		no_of_late_days = date_diff(posting_date,
-					add_days(due_date, loan_type_details.grace_period_in_days))
+			add_days(due_date, loan_type_details.grace_period_in_days))
 
 		if no_of_late_days > 0 and (not against_loan_doc.repay_from_salary):
 			penalty_amount += (entry.interest_amount * (loan_type_details.penalty_interest_rate / 100) * no_of_late_days)/365
@@ -297,7 +297,10 @@
 		if not final_due_date:
 			final_due_date = add_days(due_date, loan_type_details.grace_period_in_days)
 
-	pending_principal_amount = against_loan_doc.total_payment - against_loan_doc.total_principal_paid - against_loan_doc.total_interest_payable
+	if against_loan_doc.status == 'Disbursed':
+		pending_principal_amount = against_loan_doc.total_payment - against_loan_doc.total_principal_paid - against_loan_doc.total_interest_payable
+	else:
+		pending_principal_amount = against_loan_doc.disbursed_amount
 
 	if payment_type == "Loan Closure":
 		if due_date:
diff --git a/erpnext/loan_management/doctype/loan_security_shortfall/loan_security_shortfall.py b/erpnext/loan_management/doctype/loan_security_shortfall/loan_security_shortfall.py
index 02efe24..c3ea882 100644
--- a/erpnext/loan_management/doctype/loan_security_shortfall/loan_security_shortfall.py
+++ b/erpnext/loan_management/doctype/loan_security_shortfall/loan_security_shortfall.py
@@ -51,13 +51,19 @@
 			"valid_upto": (">=", update_time)
 		}, as_list=1))
 
-	loans = frappe.get_all('Loan', fields=['name', 'loan_amount', 'total_principal_paid'],
-		filters={'status': 'Disbursed', 'is_secured_loan': 1})
+	loans = frappe.get_all('Loan', fields=['name', 'loan_amount', 'total_principal_paid', 'total_payment',
+		'total_interest_payable', 'disbursed_amount'],
+		filters={'status': ('in',['Disbursed','Partially Disbursed']), 'is_secured_loan': 1})
 
 	loan_security_map = {}
 
 	for loan in loans:
-		outstanding_amount = loan.loan_amount - loan.total_principal_paid
+		if loan.status == 'Disbursed':
+			outstanding_amount = flt(loan.total_payment) - flt(loan.total_interest_payable) \
+				- flt(loan.total_principal_paid)
+		else:
+			outstanding_amount = loan.disbursed_amount
+
 		pledged_securities = get_pledged_security_qty(loan.name)
 		ltv_ratio = ''
 		security_value = 0.0