Merge branch 'develop' of https://github.com/frappe/erpnext into loan_repayment_type_remove
diff --git a/erpnext/loan_management/desk_page/loan/loan.json b/erpnext/loan_management/desk_page/loan/loan.json
index 3bdd1ce..fc59c19 100644
--- a/erpnext/loan_management/desk_page/loan/loan.json
+++ b/erpnext/loan_management/desk_page/loan/loan.json
@@ -3,7 +3,7 @@
   {
    "hidden": 0,
    "label": "Loan",
-   "links": "[\n    {\n        \"description\": \"Loan Type for interest and penalty rates\",\n        \"label\": \"Loan Type\",\n        \"name\": \"Loan Type\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"description\": \"Loan Applications from customers and employees.\",\n        \"label\": \"Loan Application\",\n        \"name\": \"Loan Application\",\n        \"type\": \"doctype\"\n    },\n    {   \"dependencies\": [\n            \"Loan Type\"\n        ],\n        \"description\": \"Loans provided to customers and employees.\",\n        \"label\": \"Loan\",\n        \"name\": \"Loan\",\n        \"type\": \"doctype\"\n    }\n]"
+   "links": "[\n    {\n        \"description\": \"Loan Type for interest and penalty rates\",\n        \"label\": \"Loan Type\",\n        \"name\": \"Loan Type\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"description\": \"Loan Applications from customers and employees.\",\n        \"label\": \"Loan Application\",\n        \"name\": \"Loan Application\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"description\": \"Loans provided to customers and employees.\",\n        \"label\": \"Loan\",\n        \"name\": \"Loan\",\n        \"type\": \"doctype\"\n    }\n]"
   },
   {
    "hidden": 0,
@@ -13,7 +13,7 @@
   {
    "hidden": 0,
    "label": "Disbursement and Repayment",
-   "links": "[\n    {\n        \"label\": \"Loan Disbursement\",\n        \"name\": \"Loan Disbursement\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Loan Repayment\",\n        \"name\": \"Loan Repayment\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Loan Interest Accrual\",\n        \"name\": \"Loan Interest Accrual\",\n        \"type\": \"doctype\"\n    }\n]"
+   "links": "[\n    {\n        \"label\": \"Loan Disbursement\",\n        \"name\": \"Loan Disbursement\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Loan Repayment\",\n        \"name\": \"Loan Repayment\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Loan Write Off\",\n        \"name\": \"Loan Write Off\",\n        \"type\": \"doctype\"\n    },\n    {\n        \"label\": \"Loan Interest Accrual\",\n        \"name\": \"Loan Interest Accrual\",\n        \"type\": \"doctype\"\n    }\n]"
   },
   {
    "hidden": 0,
@@ -34,10 +34,11 @@
  "docstatus": 0,
  "doctype": "Desk Page",
  "extends_another_page": 0,
+ "hide_custom": 0,
  "idx": 0,
  "is_standard": 1,
  "label": "Loan",
- "modified": "2020-06-07 19:42:14.947902",
+ "modified": "2020-10-17 12:59:50.336085",
  "modified_by": "Administrator",
  "module": "Loan Management",
  "name": "Loan",
diff --git a/erpnext/loan_management/doctype/loan/loan.js b/erpnext/loan_management/doctype/loan/loan.js
index 9b4c217..8d101b8 100644
--- a/erpnext/loan_management/doctype/loan/loan.js
+++ b/erpnext/loan_management/doctype/loan/loan.js
@@ -11,6 +11,9 @@
 		}
 	},
 	onload: function (frm) {
+		// Ignore loan security pledge on cancel of loan
+		frm.ignore_doctypes_on_cancel_all = ["Loan Security Pledge"];
+
 		frm.set_query("loan_application", function () {
 			return {
 				"filters": {
@@ -21,6 +24,14 @@
 			};
 		});
 
+		frm.set_query("loan_type", function () {
+			return {
+				"filters": {
+					"docstatus": 1
+				}
+			};
+		});
+
 		$.each(["penalty_income_account", "interest_income_account"], function(i, field) {
 			frm.set_query(field, function () {
 				return {
@@ -49,24 +60,33 @@
 
 	refresh: function (frm) {
 		if (frm.doc.docstatus == 1) {
-			if (frm.doc.status == "Sanctioned" || frm.doc.status == 'Partially Disbursed') {
+			if (["Disbursed", "Partially Disbursed"].includes(frm.doc.status) && (!frm.doc.repay_from_salary)) {
+				frm.add_custom_button(__('Request Loan Closure'), function() {
+					frm.trigger("request_loan_closure");
+				},__('Status'));
+
+				frm.add_custom_button(__('Loan Repayment'), function() {
+					frm.trigger("make_repayment_entry");
+				},__('Create'));
+			}
+
+			if (["Sanctioned", "Partially Disbursed"].includes(frm.doc.status)) {
 				frm.add_custom_button(__('Loan Disbursement'), function() {
 					frm.trigger("make_loan_disbursement");
 				},__('Create'));
 			}
 
-			if (["Disbursed", "Partially Disbursed"].includes(frm.doc.status) && (!frm.doc.repay_from_salary)) {
-				frm.add_custom_button(__('Loan Repayment'), function() {
-					frm.trigger("make_repayment_entry");
-				},__('Create'));
-
-			}
-
 			if (frm.doc.status == "Loan Closure Requested") {
 				frm.add_custom_button(__('Loan Security Unpledge'), function() {
 					frm.trigger("create_loan_security_unpledge");
 				},__('Create'));
 			}
+
+			if (["Loan Closure Requested", "Disbursed", "Partially Disbursed"].includes(frm.doc.status)) {
+				frm.add_custom_button(__('Loan Write Off'), function() {
+					frm.trigger("make_loan_write_off_entry");
+				},__('Create'));
+			}
 		}
 		frm.trigger("toggle_fields");
 	},
@@ -117,6 +137,38 @@
 		})
 	},
 
+	make_loan_write_off_entry: function(frm) {
+		frappe.call({
+			args: {
+				"loan": frm.doc.name,
+				"company": frm.doc.company,
+				"as_dict": 1
+			},
+			method: "erpnext.loan_management.doctype.loan.loan.make_loan_write_off",
+			callback: function (r) {
+				if (r.message)
+					var doc = frappe.model.sync(r.message)[0];
+				frappe.set_route("Form", doc.doctype, doc.name);
+			}
+		})
+	},
+
+	request_loan_closure: function(frm) {
+		frappe.confirm(__("Do you really want to close this loan"),
+			function() {
+				frappe.call({
+					args: {
+						'loan': frm.doc.name
+					},
+					method: "erpnext.loan_management.doctype.loan.loan.request_loan_closure",
+					callback: function() {
+						frm.reload_doc();
+					}
+				});
+			}
+		);
+	},
+
 	create_loan_security_unpledge: function(frm) {
 		frappe.call({
 			method: "erpnext.loan_management.doctype.loan.loan.unpledge_security",
diff --git a/erpnext/loan_management/doctype/loan/loan.json b/erpnext/loan_management/doctype/loan/loan.json
index aa5e21b..b613d22 100644
--- a/erpnext/loan_management/doctype/loan/loan.json
+++ b/erpnext/loan_management/doctype/loan/loan.json
@@ -43,6 +43,7 @@
   "section_break_17",
   "total_payment",
   "total_principal_paid",
+  "written_off_amount",
   "column_break_19",
   "total_interest_payable",
   "total_amount_paid",
@@ -75,6 +76,7 @@
    "fieldname": "loan_application",
    "fieldtype": "Link",
    "label": "Loan Application",
+   "no_copy": 1,
    "options": "Loan Application"
   },
   {
@@ -148,7 +150,8 @@
    "depends_on": "eval:doc.status==\"Disbursed\"",
    "fieldname": "disbursement_date",
    "fieldtype": "Date",
-   "label": "Disbursement Date"
+   "label": "Disbursement Date",
+   "no_copy": 1
   },
   {
    "depends_on": "is_term_loan",
@@ -252,6 +255,7 @@
    "fieldname": "total_payment",
    "fieldtype": "Currency",
    "label": "Total Payable Amount",
+   "no_copy": 1,
    "options": "Company:company:default_currency",
    "read_only": 1
   },
@@ -265,6 +269,7 @@
    "fieldname": "total_interest_payable",
    "fieldtype": "Currency",
    "label": "Total Interest Payable",
+   "no_copy": 1,
    "options": "Company:company:default_currency",
    "read_only": 1
   },
@@ -273,6 +278,7 @@
    "fieldname": "total_amount_paid",
    "fieldtype": "Currency",
    "label": "Total Amount Paid",
+   "no_copy": 1,
    "options": "Company:company:default_currency",
    "read_only": 1
   },
@@ -289,8 +295,7 @@
    "default": "0",
    "fieldname": "is_secured_loan",
    "fieldtype": "Check",
-   "label": "Is Secured Loan",
-   "read_only": 1
+   "label": "Is Secured Loan"
   },
   {
    "default": "0",
@@ -313,6 +318,7 @@
    "fieldname": "total_principal_paid",
    "fieldtype": "Currency",
    "label": "Total Principal Paid",
+   "no_copy": 1,
    "options": "Company:company:default_currency",
    "read_only": 1
   },
@@ -320,6 +326,7 @@
    "fieldname": "disbursed_amount",
    "fieldtype": "Currency",
    "label": "Disbursed Amount",
+   "no_copy": 1,
    "options": "Company:company:default_currency",
    "read_only": 1
   },
@@ -328,13 +335,22 @@
    "fieldname": "maximum_loan_amount",
    "fieldtype": "Currency",
    "label": "Maximum Loan Amount",
+   "no_copy": 1,
    "options": "Company:company:default_currency",
    "read_only": 1
+  },
+  {
+   "fieldname": "written_off_amount",
+   "fieldtype": "Currency",
+   "label": "Written Off Amount",
+   "no_copy": 1,
+   "options": "Company:company:default_currency"
   }
  ],
+ "index_web_pages_for_search": 1,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-08-01 12:36:11.255233",
+ "modified": "2020-10-22 11:03:43.697394",
  "modified_by": "Administrator",
  "module": "Loan Management",
  "name": "Loan",
diff --git a/erpnext/loan_management/doctype/loan/loan.py b/erpnext/loan_management/doctype/loan/loan.py
index d1b7589..8405d6e 100644
--- a/erpnext/loan_management/doctype/loan/loan.py
+++ b/erpnext/loan_management/doctype/loan/loan.py
@@ -9,6 +9,7 @@
 from frappe.utils import flt, rounded, add_months, nowdate, getdate, now_datetime
 from erpnext.loan_management.doctype.loan_security_unpledge.loan_security_unpledge import get_pledged_security_qty
 from erpnext.controllers.accounts_controller import AccountsController
+from erpnext.loan_management.doctype.loan_repayment.loan_repayment import calculate_amounts
 
 class Loan(AccountsController):
 	def validate(self):
@@ -137,9 +138,12 @@
 				})
 
 	def unlink_loan_security_pledge(self):
-		frappe.db.sql("""UPDATE `tabLoan Security Pledge` SET
-			loan = '', status = 'Unpledged'
-			where name = %s """, (self.loan_security_pledge))
+		pledges = frappe.get_all('Loan Security Pledge', fields=['name'], filters={'loan': self.name})
+		pledge_list = [d.name for d in pledges]
+		if pledge_list:
+			frappe.db.sql("""UPDATE `tabLoan Security Pledge` SET
+				loan = '', status = 'Unpledged'
+				where name in (%s) """ % (', '.join(['%s']*len(pledge_list))), tuple(pledge_list)) #nosec
 
 def update_total_amount_paid(doc):
 	total_amount_paid = 0
@@ -183,6 +187,24 @@
 	return monthly_repayment_amount
 
 @frappe.whitelist()
+def request_loan_closure(loan, posting_date=None):
+	if not posting_date:
+		posting_date = getdate()
+
+	amounts = calculate_amounts(loan, posting_date)
+	pending_amount = amounts['payable_amount'] + amounts['unaccrued_interest']
+
+	loan_type = frappe.get_value('Loan', loan, 'loan_type')
+	write_off_limit = frappe.get_value('Loan Type', loan_type, 'write_off_amount')
+
+	# checking greater than 0 as there may be some minor precision error
+	if pending_amount < write_off_limit:
+		# update status as loan closure requested
+		frappe.db.set_value('Loan', loan, 'status', 'Loan Closure Requested')
+	else:
+		frappe.throw(_("Cannot close loan as there is an outstanding of {0}").format(pending_amount))
+
+@frappe.whitelist()
 def get_loan_application(loan_application):
 	loan = frappe.get_doc("Loan Application", loan_application)
 	if loan:
@@ -200,6 +222,7 @@
 	disbursement_entry.applicant = applicant
 	disbursement_entry.company = company
 	disbursement_entry.disbursement_date = nowdate()
+	disbursement_entry.posting_date = nowdate()
 
 	disbursement_entry.disbursed_amount = pending_amount
 	if as_dict:
@@ -223,6 +246,38 @@
 		return repayment_entry
 
 @frappe.whitelist()
+def make_loan_write_off(loan, company=None, posting_date=None, amount=0, as_dict=0):
+	if not company:
+		company = frappe.get_value('Loan', loan, 'company')
+
+	if not posting_date:
+		posting_date = getdate()
+
+	amounts = calculate_amounts(loan, posting_date)
+	pending_amount = amounts['pending_principal_amount']
+
+	if amount and (amount > pending_amount):
+		frappe.throw('Write Off amount cannot be greater than pending loan amount')
+
+	if not amount:
+		amount = pending_amount
+
+	# get default write off account from company master
+	write_off_account = frappe.get_value('Company', company, 'write_off_account')
+
+	write_off = frappe.new_doc('Loan Write Off')
+	write_off.loan = loan
+	write_off.posting_date = posting_date
+	write_off.write_off_account = write_off_account
+	write_off.write_off_amount = amount
+	write_off.save()
+
+	if as_dict:
+		return write_off.as_dict()
+	else:
+		return write_off
+
+@frappe.whitelist()
 def unpledge_security(loan=None, loan_security_pledge=None, as_dict=0, save=0, submit=0, approve=0):
 	# if loan is passed it will be considered as full unpledge
 	if loan:
diff --git a/erpnext/loan_management/doctype/loan/loan_dashboard.py b/erpnext/loan_management/doctype/loan/loan_dashboard.py
index 90d5ae2..7a8190f 100644
--- a/erpnext/loan_management/doctype/loan/loan_dashboard.py
+++ b/erpnext/loan_management/doctype/loan/loan_dashboard.py
@@ -13,7 +13,7 @@
 				'items': ['Loan Security Pledge', 'Loan Security Shortfall', 'Loan Disbursement']
 			},
 			{
-				'items': ['Loan Repayment', 'Loan Interest Accrual', 'Loan Security Unpledge']
+				'items': ['Loan Repayment', 'Loan Interest Accrual', 'Loan Write Off', 'Loan Security Unpledge']
 			}
 		]
 	}
\ No newline at end of file
diff --git a/erpnext/loan_management/doctype/loan/test_loan.py b/erpnext/loan_management/doctype/loan/test_loan.py
index 5a4a19a..1634697 100644
--- a/erpnext/loan_management/doctype/loan/test_loan.py
+++ b/erpnext/loan_management/doctype/loan/test_loan.py
@@ -14,7 +14,7 @@
 	process_loan_interest_accrual_for_term_loans)
 from erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual import days_in_year
 from erpnext.loan_management.doctype.process_loan_security_shortfall.process_loan_security_shortfall import create_process_loan_security_shortfall
-from erpnext.loan_management.doctype.loan.loan import unpledge_security
+from erpnext.loan_management.doctype.loan.loan import unpledge_security, request_loan_closure, make_loan_write_off
 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
@@ -132,7 +132,7 @@
 		loan_application = create_loan_application('_Test Company', self.applicant2, 'Demand Loan', pledge)
 		create_pledge(loan_application)
 
-		loan = create_demand_loan(self.applicant2, "Demand Loan", loan_application, posting_date=get_first_day(nowdate()))
+		loan = create_demand_loan(self.applicant2, "Demand Loan", loan_application, posting_date='2019-10-01')
 		loan.submit()
 
 		self.assertEquals(loan.loan_amount, 1000000)
@@ -149,23 +149,23 @@
 
 		process_loan_interest_accrual_for_demand_loans(posting_date = last_date)
 
-		repayment_entry = create_repayment_entry(loan.name, self.applicant2, add_days(last_date, 10), "Regular Payment", 111118.68)
+		repayment_entry = create_repayment_entry(loan.name, self.applicant2, add_days(last_date, 10), 111118.68)
 		repayment_entry.save()
 		repayment_entry.submit()
 
 		penalty_amount = (accrued_interest_amount * 4 * 25) / (100 * days_in_year(get_datetime(first_date).year))
 		self.assertEquals(flt(repayment_entry.penalty_amount, 2), flt(penalty_amount, 2))
 
-		amounts = frappe.db.get_value('Loan Interest Accrual', {'loan': loan.name}, ['paid_interest_amount',
-			'paid_principal_amount'])
+		amounts = frappe.db.get_all('Loan Interest Accrual', {'loan': loan.name}, ['paid_interest_amount'])
 
 		loan.load_from_db()
 
-		self.assertEquals(amounts[0], repayment_entry.interest_payable)
+		total_interest_paid = amounts[0]['paid_interest_amount'] + amounts[1]['paid_interest_amount']
+		self.assertEquals(amounts[1]['paid_interest_amount'], repayment_entry.interest_payable)
 		self.assertEquals(flt(loan.total_principal_paid, 2), flt(repayment_entry.amount_paid -
-			 penalty_amount - amounts[0], 2))
+			 penalty_amount - total_interest_paid, 2))
 
-	def test_loan_closure_repayment(self):
+	def test_loan_closure(self):
 		pledge = [{
 			"loan_security": "Test Security 1",
 			"qty": 4000.00
@@ -174,7 +174,7 @@
 		loan_application = create_loan_application('_Test Company', self.applicant2, 'Demand Loan', pledge)
 		create_pledge(loan_application)
 
-		loan = create_demand_loan(self.applicant2, "Demand Loan", loan_application, posting_date=get_first_day(nowdate()))
+		loan = create_demand_loan(self.applicant2, "Demand Loan", loan_application, posting_date='2019-10-01')
 		loan.submit()
 
 		self.assertEquals(loan.loan_amount, 1000000)
@@ -196,14 +196,16 @@
 		process_loan_interest_accrual_for_demand_loans(posting_date = last_date)
 
 		repayment_entry = create_repayment_entry(loan.name, self.applicant2, add_days(last_date, 6),
-			"Loan Closure", flt(loan.loan_amount + accrued_interest_amount))
+			flt(loan.loan_amount + accrued_interest_amount))
+
 		repayment_entry.submit()
 
 		amount = frappe.db.get_value('Loan Interest Accrual', {'loan': loan.name}, ['sum(paid_interest_amount)'])
 
-		self.assertEquals(flt(amount, 2),flt(accrued_interest_amount, 2))
+		self.assertEquals(flt(amount, 0),flt(accrued_interest_amount, 0))
 		self.assertEquals(flt(repayment_entry.penalty_amount, 5), 0)
 
+		request_loan_closure(loan.name)
 		loan.load_from_db()
 		self.assertEquals(loan.status, "Loan Closure Requested")
 
@@ -230,8 +232,7 @@
 
 		process_loan_interest_accrual_for_term_loans(posting_date=nowdate())
 
-		repayment_entry = create_repayment_entry(loan.name, self.applicant2, add_days(nowdate(), 5),
-			"Regular Payment", 89768.75)
+		repayment_entry = create_repayment_entry(loan.name, self.applicant2, add_days(nowdate(), 5), 89768.75)
 
 		repayment_entry.submit()
 
@@ -281,7 +282,7 @@
 		loan_application = create_loan_application('_Test Company', self.applicant2, 'Demand Loan', pledge)
 		create_pledge(loan_application)
 
-		loan = create_demand_loan(self.applicant2, "Demand Loan", loan_application, posting_date=get_first_day(nowdate()))
+		loan = create_demand_loan(self.applicant2, "Demand Loan", loan_application, posting_date='2019-10-01')
 		loan.submit()
 
 		self.assertEquals(loan.loan_amount, 1000000)
@@ -299,10 +300,10 @@
 		make_loan_disbursement_entry(loan.name, loan.loan_amount, disbursement_date=first_date)
 		process_loan_interest_accrual_for_demand_loans(posting_date = last_date)
 
-		repayment_entry = create_repayment_entry(loan.name, self.applicant2, add_days(last_date, 6),
-			"Loan Closure", flt(loan.loan_amount + accrued_interest_amount))
+		repayment_entry = create_repayment_entry(loan.name, self.applicant2, add_days(last_date, 6), flt(loan.loan_amount + accrued_interest_amount))
 		repayment_entry.submit()
 
+		request_loan_closure(loan.name)
 		loan.load_from_db()
 		self.assertEquals(loan.status, "Loan Closure Requested")
 
@@ -317,9 +318,9 @@
 		self.assertEqual(loan.status, 'Closed')
 		self.assertEquals(sum(pledged_qty.values()), 0)
 
-		amounts = amounts = calculate_amounts(loan.name, add_days(last_date, 6), "Regular Repayment")
-		self.assertEqual(amounts['pending_principal_amount'], 0)
-		self.assertEqual(amounts['payable_principal_amount'], 0)
+		amounts = amounts = calculate_amounts(loan.name, add_days(last_date, 6))
+		self.assertTrue(amounts['pending_principal_amount'] < 0)
+		self.assertEquals(amounts['payable_principal_amount'], 0.0)
 		self.assertEqual(amounts['interest_amount'], 0)
 
 	def test_disbursal_check_with_shortfall(self):
@@ -381,7 +382,7 @@
 		loan_application = create_loan_application('_Test Company', self.applicant2, 'Demand Loan', pledge)
 		create_pledge(loan_application)
 
-		loan = create_demand_loan(self.applicant2, "Demand Loan", loan_application, posting_date=get_first_day(nowdate()))
+		loan = create_demand_loan(self.applicant2, "Demand Loan", loan_application, posting_date='2019-10-01')
 		loan.submit()
 
 		self.assertEquals(loan.loan_amount, 1000000)
@@ -399,20 +400,192 @@
 		make_loan_disbursement_entry(loan.name, loan.loan_amount, disbursement_date=first_date)
 		process_loan_interest_accrual_for_demand_loans(posting_date = last_date)
 
-		amounts = calculate_amounts(loan.name, add_days(last_date, 6), "Regular Repayment")
+		amounts = calculate_amounts(loan.name, add_days(last_date, 6))
 
-		repayment_entry = create_repayment_entry(loan.name, self.applicant2, add_days(last_date, 6),
-			"Loan Closure", flt(loan.loan_amount + accrued_interest_amount))
+		repayment_entry = create_repayment_entry(loan.name, self.applicant2, add_days(last_date, 6), flt(loan.loan_amount + accrued_interest_amount))
 		repayment_entry.submit()
 
 		amounts = frappe.db.get_value('Loan Interest Accrual', {'loan': loan.name}, ['paid_interest_amount',
 			'paid_principal_amount'])
 
+		request_loan_closure(loan.name)
 		loan.load_from_db()
 		self.assertEquals(loan.status, "Loan Closure Requested")
 
-		amounts = calculate_amounts(loan.name, add_days(last_date, 6), "Regular Repayment")
-		self.assertEquals(amounts['pending_principal_amount'], 0.0)
+		amounts = calculate_amounts(loan.name, add_days(last_date, 6))
+		self.assertTrue(amounts['pending_principal_amount'] < 0.0)
+
+	def test_partial_unaccrued_interest_payment(self):
+		pledge = [{
+			"loan_security": "Test Security 1",
+			"qty": 4000.00
+		}]
+
+		loan_application = create_loan_application('_Test Company', self.applicant2, 'Demand Loan', pledge)
+		create_pledge(loan_application)
+
+		loan = create_demand_loan(self.applicant2, "Demand Loan", loan_application, posting_date='2019-10-01')
+		loan.submit()
+
+		self.assertEquals(loan.loan_amount, 1000000)
+
+		first_date = '2019-10-01'
+		last_date = '2019-10-30'
+
+		no_of_days = date_diff(last_date, first_date) + 1
+
+		no_of_days += 5.5
+
+		# get partial unaccrued interest amount
+		paid_amount = (loan.loan_amount * loan.rate_of_interest * no_of_days) \
+			/ (days_in_year(get_datetime(first_date).year) * 100)
+
+		make_loan_disbursement_entry(loan.name, loan.loan_amount, disbursement_date=first_date)
+		process_loan_interest_accrual_for_demand_loans(posting_date = last_date)
+
+		amounts = calculate_amounts(loan.name, add_days(last_date, 6))
+
+		repayment_entry = create_repayment_entry(loan.name, self.applicant2, add_days(last_date, 6),
+			paid_amount)
+
+		repayment_entry.submit()
+		repayment_entry.load_from_db()
+
+		partial_accrued_interest_amount = (loan.loan_amount * loan.rate_of_interest * 5) \
+			/ (days_in_year(get_datetime(first_date).year) * 100)
+
+		interest_amount = flt(amounts['interest_amount'] + partial_accrued_interest_amount, 2)
+		self.assertEqual(flt(repayment_entry.total_interest_paid, 0), flt(interest_amount, 0))
+
+	def test_penalty(self):
+		pledge = [{
+			"loan_security": "Test Security 1",
+			"qty": 4000.00
+		}]
+
+		loan_application = create_loan_application('_Test Company', self.applicant2, 'Demand Loan', pledge)
+		create_pledge(loan_application)
+
+		loan = create_demand_loan(self.applicant2, "Demand Loan", loan_application, posting_date='2019-10-01')
+		loan.submit()
+
+		self.assertEquals(loan.loan_amount, 1000000)
+
+		first_date = '2019-10-01'
+		last_date = '2019-10-30'
+
+		make_loan_disbursement_entry(loan.name, loan.loan_amount, disbursement_date=first_date)
+		process_loan_interest_accrual_for_demand_loans(posting_date = last_date)
+
+		amounts = calculate_amounts(loan.name, add_days(last_date, 1))
+		paid_amount = amounts['interest_amount']/2
+
+		repayment_entry = create_repayment_entry(loan.name, self.applicant2, add_days(last_date, 6),
+			paid_amount)
+
+		repayment_entry.submit()
+
+		# 30 days - grace period
+		penalty_days = 30 - 5
+		penalty_applicable_amount = flt(amounts['interest_amount']/2, 2)
+		penalty_amount = flt((((penalty_applicable_amount * 25) / 100) * penalty_days)/365, 2)
+		process = process_loan_interest_accrual_for_demand_loans(posting_date = '2019-11-30')
+
+		calculated_penalty_amount = frappe.db.get_value('Loan Interest Accrual',
+			{'process_loan_interest_accrual': process, 'loan': loan.name}, 'penalty_amount')
+
+		self.assertEquals(calculated_penalty_amount, penalty_amount)
+
+	def test_loan_write_off_limit(self):
+		pledge = [{
+			"loan_security": "Test Security 1",
+			"qty": 4000.00
+		}]
+
+		loan_application = create_loan_application('_Test Company', self.applicant2, 'Demand Loan', pledge)
+		create_pledge(loan_application)
+
+		loan = create_demand_loan(self.applicant2, "Demand Loan", loan_application, posting_date='2019-10-01')
+		loan.submit()
+
+		self.assertEquals(loan.loan_amount, 1000000)
+
+		first_date = '2019-10-01'
+		last_date = '2019-10-30'
+
+		no_of_days = date_diff(last_date, first_date) + 1
+		no_of_days += 6
+
+		accrued_interest_amount = (loan.loan_amount * loan.rate_of_interest * no_of_days) \
+			/ (days_in_year(get_datetime(first_date).year) * 100)
+
+		make_loan_disbursement_entry(loan.name, loan.loan_amount, disbursement_date=first_date)
+		process_loan_interest_accrual_for_demand_loans(posting_date = last_date)
+
+		# repay 50 less so that it can be automatically written off
+		repayment_entry = create_repayment_entry(loan.name, self.applicant2, add_days(last_date, 6),
+			flt(loan.loan_amount + accrued_interest_amount - 50))
+
+		repayment_entry.submit()
+
+		amount = frappe.db.get_value('Loan Interest Accrual', {'loan': loan.name}, ['sum(paid_interest_amount)'])
+
+		self.assertEquals(flt(amount, 0),flt(accrued_interest_amount, 0))
+		self.assertEquals(flt(repayment_entry.penalty_amount, 5), 0)
+
+		amounts = calculate_amounts(loan.name, add_days(last_date, 6))
+		self.assertEquals(flt(amounts['pending_principal_amount'], 0), 50)
+
+		request_loan_closure(loan.name)
+		loan.load_from_db()
+		self.assertEquals(loan.status, "Loan Closure Requested")
+
+	def test_loan_amount_write_off(self):
+		pledge = [{
+			"loan_security": "Test Security 1",
+			"qty": 4000.00
+		}]
+
+		loan_application = create_loan_application('_Test Company', self.applicant2, 'Demand Loan', pledge)
+		create_pledge(loan_application)
+
+		loan = create_demand_loan(self.applicant2, "Demand Loan", loan_application, posting_date='2019-10-01')
+		loan.submit()
+
+		self.assertEquals(loan.loan_amount, 1000000)
+
+		first_date = '2019-10-01'
+		last_date = '2019-10-30'
+
+		no_of_days = date_diff(last_date, first_date) + 1
+		no_of_days += 6
+
+		accrued_interest_amount = (loan.loan_amount * loan.rate_of_interest * no_of_days) \
+			/ (days_in_year(get_datetime(first_date).year) * 100)
+
+		make_loan_disbursement_entry(loan.name, loan.loan_amount, disbursement_date=first_date)
+		process_loan_interest_accrual_for_demand_loans(posting_date = last_date)
+
+		# repay 100 less so that it can be automatically written off
+		repayment_entry = create_repayment_entry(loan.name, self.applicant2, add_days(last_date, 6),
+			flt(loan.loan_amount + accrued_interest_amount - 100))
+
+		repayment_entry.submit()
+
+		amount = frappe.db.get_value('Loan Interest Accrual', {'loan': loan.name}, ['sum(paid_interest_amount)'])
+
+		self.assertEquals(flt(amount, 0),flt(accrued_interest_amount, 0))
+		self.assertEquals(flt(repayment_entry.penalty_amount, 5), 0)
+
+		amounts = calculate_amounts(loan.name, add_days(last_date, 6))
+		self.assertEquals(flt(amounts['pending_principal_amount'], 0), 100)
+
+		we = make_loan_write_off(loan.name, amount=amounts['pending_principal_amount'])
+		we.submit()
+
+		amounts = calculate_amounts(loan.name, add_days(last_date, 6))
+		self.assertEquals(flt(amounts['pending_principal_amount'], 0), 0)
+
 
 def create_loan_accounts():
 	if not frappe.db.exists("Account", "Loans and Advances (Assets) - _TC"):
@@ -496,7 +669,8 @@
 			"interest_income_account": interest_income_account,
 			"penalty_income_account": penalty_income_account,
 			"repayment_method": repayment_method,
-			"repayment_periods": repayment_periods
+			"repayment_periods": repayment_periods,
+			"write_off_amount": 100
 		}).insert()
 
 		loan_type.submit()
@@ -532,7 +706,7 @@
 			"haircut": 50.00,
 		}).insert(ignore_permissions=True)
 
-def create_loan_security_pledge(applicant, pledges, loan_application):
+def create_loan_security_pledge(applicant, pledges, loan_application=None, loan=None):
 
 	lsp = frappe.new_doc("Loan Security Pledge")
 	lsp.applicant_type = 'Customer'
@@ -540,11 +714,13 @@
 	lsp.company = "_Test Company"
 	lsp.loan_application = loan_application
 
+	if loan:
+		lsp.loan = loan
+
 	for pledge in pledges:
 		lsp.append('securities', {
 			"loan_security": pledge['loan_security'],
-			"qty": pledge['qty'],
-			"haircut": pledge['haircut']
+			"qty": pledge['qty']
 		})
 
 	lsp.save()
@@ -582,12 +758,11 @@
 			"valid_upto": to_date
 		}).insert(ignore_permissions=True)
 
-def create_repayment_entry(loan, applicant, posting_date, payment_type, paid_amount):
+def create_repayment_entry(loan, applicant, posting_date, paid_amount):
 
 	lr = frappe.get_doc({
 		"doctype": "Loan Repayment",
 		"against_loan": loan,
-		"payment_type": payment_type,
 		"company": "_Test Company",
 		"posting_date": posting_date or nowdate(),
 		"applicant": applicant,
diff --git a/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.json b/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.json
index c437a98..89f671b 100644
--- a/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.json
+++ b/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.json
@@ -26,19 +26,23 @@
   {
    "fieldname": "against_loan",
    "fieldtype": "Link",
+   "in_list_view": 1,
    "label": "Against Loan ",
-   "options": "Loan"
+   "options": "Loan",
+   "reqd": 1
   },
   {
    "fieldname": "disbursement_date",
    "fieldtype": "Date",
-   "label": "Disbursement Date"
+   "label": "Disbursement Date",
+   "reqd": 1
   },
   {
    "fieldname": "disbursed_amount",
    "fieldtype": "Currency",
    "label": "Disbursed Amount",
-   "options": "Company:company:default_currency"
+   "options": "Company:company:default_currency",
+   "reqd": 1
   },
   {
    "fieldname": "amended_from",
@@ -53,17 +57,21 @@
    "fetch_from": "against_loan.company",
    "fieldname": "company",
    "fieldtype": "Link",
+   "in_list_view": 1,
    "label": "Company",
    "options": "Company",
-   "read_only": 1
+   "read_only": 1,
+   "reqd": 1
   },
   {
    "fetch_from": "against_loan.applicant",
    "fieldname": "applicant",
    "fieldtype": "Dynamic Link",
+   "in_list_view": 1,
    "label": "Applicant",
    "options": "applicant_type",
-   "read_only": 1
+   "read_only": 1,
+   "reqd": 1
   },
   {
    "collapsible": 1,
@@ -102,9 +110,11 @@
    "fetch_from": "against_loan.applicant_type",
    "fieldname": "applicant_type",
    "fieldtype": "Select",
+   "in_list_view": 1,
    "label": "Applicant Type",
    "options": "Employee\nMember\nCustomer",
-   "read_only": 1
+   "read_only": 1,
+   "reqd": 1
   },
   {
    "fieldname": "bank_account",
@@ -117,9 +127,10 @@
    "fieldtype": "Column Break"
   }
  ],
+ "index_web_pages_for_search": 1,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-04-29 05:20:41.629911",
+ "modified": "2020-10-16 10:04:26.229216",
  "modified_by": "Administrator",
  "module": "Loan Management",
  "name": "Loan Disbursement",
diff --git a/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py b/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py
index 260fada..bfdc8b4 100644
--- a/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py
+++ b/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py
@@ -74,7 +74,7 @@
 
 			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),
-					loan=self.against_loan)
+					loan=self.against_loan, accrual_type="Disbursement")
 
 			if disbursed_amount > loan_details.loan_amount:
 				topup_amount = disbursed_amount - loan_details.loan_amount
diff --git a/erpnext/loan_management/doctype/loan_disbursement/test_loan_disbursement.py b/erpnext/loan_management/doctype/loan_disbursement/test_loan_disbursement.py
index 2cb2637..aaaeea8 100644
--- a/erpnext/loan_management/doctype/loan_disbursement/test_loan_disbursement.py
+++ b/erpnext/loan_management/doctype/loan_disbursement/test_loan_disbursement.py
@@ -8,9 +8,10 @@
 from erpnext.loan_management.doctype.loan.test_loan import (create_loan_type, create_loan_security_pledge, create_repayment_entry, create_loan_application,
 	make_loan_disbursement_entry, create_loan_accounts, create_loan_security_type, create_loan_security, create_demand_loan, create_loan_security_price)
 from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import process_loan_interest_accrual_for_demand_loans
-from erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual import days_in_year
+from erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual import days_in_year, get_per_day_interest
 from erpnext.selling.doctype.customer.test_customer import get_customer_dict
 from erpnext.loan_management.doctype.loan_application.loan_application import create_pledge
+from erpnext.loan_management.doctype.loan_repayment.loan_repayment import calculate_amounts
 
 class TestLoanDisbursement(unittest.TestCase):
 
@@ -60,8 +61,7 @@
 		self.assertRaises(frappe.ValidationError, make_loan_disbursement_entry, loan.name,
 			500000, first_date)
 
-		repayment_entry = create_repayment_entry(loan.name, self.applicant, add_days(get_last_day(nowdate()), 5),
-			"Regular Payment", 611095.89)
+		repayment_entry = create_repayment_entry(loan.name, self.applicant, add_days(get_last_day(nowdate()), 5), 611095.89)
 
 		repayment_entry.submit()
 		loan.reload()
@@ -69,3 +69,44 @@
 		# After repayment loan disbursement entry should go through
 		make_loan_disbursement_entry(loan.name, 500000, disbursement_date=add_days(last_date, 16))
 
+	def test_loan_topup_with_additional_pledge(self):
+		pledge = [{
+			"loan_security": "Test Security 1",
+			"qty": 4000.00
+		}]
+
+		loan_application = create_loan_application('_Test Company', self.applicant, 'Demand Loan', pledge)
+		create_pledge(loan_application)
+
+		loan = create_demand_loan(self.applicant, "Demand Loan", loan_application, posting_date='2019-10-01')
+		loan.submit()
+
+		self.assertEquals(loan.loan_amount, 1000000)
+
+		first_date = '2019-10-01'
+		last_date = '2019-10-30'
+
+		# Disbursed 10,00,000 amount
+		make_loan_disbursement_entry(loan.name, loan.loan_amount, disbursement_date=first_date)
+		process_loan_interest_accrual_for_demand_loans(posting_date = last_date)
+		amounts = calculate_amounts(loan.name, add_days(last_date, 1))
+
+		previous_interest = amounts['interest_amount']
+
+		pledge1 = [{
+			"loan_security": "Test Security 1",
+			"qty": 2000.00
+		}]
+
+		create_loan_security_pledge(self.applicant, pledge1, loan=loan.name)
+
+		# Topup 500000
+		make_loan_disbursement_entry(loan.name, 500000, disbursement_date=add_days(last_date, 1))
+		process_loan_interest_accrual_for_demand_loans(posting_date = add_days(last_date, 15))
+		amounts = calculate_amounts(loan.name, add_days(last_date, 15))
+
+		per_day_interest = get_per_day_interest(1500000, 13.5, '2019-10-30')
+		interest = per_day_interest * 15
+
+		self.assertEquals(amounts['pending_principal_amount'], 1500000)
+		self.assertEquals(amounts['interest_amount'], flt(interest + previous_interest, 2))
diff --git a/erpnext/loan_management/doctype/loan_interest_accrual/loan_interest_accrual.json b/erpnext/loan_management/doctype/loan_interest_accrual/loan_interest_accrual.json
index 5fc3e8f..893609e 100644
--- a/erpnext/loan_management/doctype/loan_interest_accrual/loan_interest_accrual.json
+++ b/erpnext/loan_management/doctype/loan_interest_accrual/loan_interest_accrual.json
@@ -14,6 +14,7 @@
   "column_break_4",
   "company",
   "posting_date",
+  "accrual_type",
   "is_term_loan",
   "section_break_7",
   "pending_principal_amount",
@@ -22,6 +23,7 @@
   "column_break_14",
   "interest_amount",
   "paid_interest_amount",
+  "penalty_amount",
   "section_break_15",
   "process_loan_interest_accrual",
   "repayment_schedule_name",
@@ -149,12 +151,25 @@
    "fieldtype": "Currency",
    "label": "Paid Interest Amount",
    "options": "Company:company:default_currency"
+  },
+  {
+   "fieldname": "accrual_type",
+   "fieldtype": "Select",
+   "label": "Accrual Type",
+   "options": "Regular\nRepayment\nDisbursement"
+  },
+  {
+   "fieldname": "penalty_amount",
+   "fieldtype": "Currency",
+   "label": "Penalty Amount",
+   "options": "Company:company:default_currency"
   }
  ],
  "in_create": 1,
+ "index_web_pages_for_search": 1,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-04-16 11:24:23.258404",
+ "modified": "2020-10-11 11:17:44.704694",
  "modified_by": "Administrator",
  "module": "Loan Management",
  "name": "Loan Interest Accrual",
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 2d959bf..1fc41f9 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
@@ -22,7 +22,6 @@
 		if not self.interest_amount and not self.payable_principal_amount:
 			frappe.throw(_("Interest Amount or Principal Amount is mandatory"))
 
-
 	def on_submit(self):
 		self.make_gl_entries()
 
@@ -79,19 +78,23 @@
 # For Eg: If Loan disbursement date is '01-09-2019' and disbursed amount is 1000000 and
 # rate of interest is 13.5 then first loan interest accural will be on '01-10-2019'
 # which means interest will be accrued for 30 days which should be equal to 11095.89
-def calculate_accrual_amount_for_demand_loans(loan, posting_date, process_loan_interest):
+def calculate_accrual_amount_for_demand_loans(loan, posting_date, process_loan_interest, accrual_type):
+	from erpnext.loan_management.doctype.loan_repayment.loan_repayment import calculate_amounts
+
 	no_of_days = get_no_of_days_for_interest_accural(loan, posting_date)
+	precision = cint(frappe.db.get_default("currency_precision")) or 2
 
 	if no_of_days <= 0:
 		return
 
 	if loan.status == 'Disbursed':
 		pending_principal_amount = flt(loan.total_payment) - flt(loan.total_interest_payable) \
-			- flt(loan.total_principal_paid)
+			- flt(loan.total_principal_paid) - flt(loan.written_off_amount)
 	else:
-		pending_principal_amount = loan.disbursed_amount
+		pending_principal_amount = flt(loan.disbursed_amount) - flt(loan.total_interest_payable) \
+			- flt(loan.total_principal_paid) - flt(loan.written_off_amount)
 
-	interest_per_day = (pending_principal_amount * loan.rate_of_interest) / (days_in_year(get_datetime(posting_date).year) * 100)
+	interest_per_day = get_per_day_interest(pending_principal_amount, loan.rate_of_interest, posting_date)
 	payable_interest = interest_per_day * no_of_days
 
 	args = frappe._dict({
@@ -102,13 +105,16 @@
 		'loan_account': loan.loan_account,
 		'pending_principal_amount': pending_principal_amount,
 		'interest_amount': payable_interest,
+		'penalty_amount': calculate_amounts(loan.name, posting_date)['penalty_amount'],
 		'process_loan_interest': process_loan_interest,
-		'posting_date': posting_date
+		'posting_date': posting_date,
+		'accrual_type': accrual_type
 	})
 
-	make_loan_interest_accrual_entry(args)
+	if flt(payable_interest, precision) > 0.0:
+		make_loan_interest_accrual_entry(args)
 
-def make_accrual_interest_entry_for_demand_loans(posting_date, process_loan_interest, open_loans=None, loan_type=None):
+def make_accrual_interest_entry_for_demand_loans(posting_date, process_loan_interest, open_loans=None, loan_type=None, accrual_type="Regular"):
 	query_filters = {
 		"status": ('in', ['Disbursed', 'Partially Disbursed']),
 		"docstatus": 1
@@ -123,11 +129,11 @@
 		open_loans = frappe.get_all("Loan",
 			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"],
+				"rate_of_interest", "total_interest_payable", "written_off_amount", "total_principal_paid", "repayment_start_date"],
 			filters=query_filters)
 
 	for loan in open_loans:
-		calculate_accrual_amount_for_demand_loans(loan, posting_date, process_loan_interest)
+		calculate_accrual_amount_for_demand_loans(loan, posting_date, process_loan_interest, accrual_type)
 
 def make_accrual_interest_entry_for_term_loans(posting_date, process_loan_interest, term_loan=None, loan_type=None):
 	curr_date = posting_date or add_days(nowdate(), 1)
@@ -192,31 +198,33 @@
 	loan_interest_accrual.loan_account = args.loan_account
 	loan_interest_accrual.pending_principal_amount = flt(args.pending_principal_amount, precision)
 	loan_interest_accrual.interest_amount = flt(args.interest_amount, precision)
+	loan_interest_accrual.penalty_amount = flt(args.penalty_amount, precision)
 	loan_interest_accrual.posting_date = args.posting_date or nowdate()
 	loan_interest_accrual.process_loan_interest_accrual = args.process_loan_interest
 	loan_interest_accrual.repayment_schedule_name = args.repayment_schedule_name
 	loan_interest_accrual.payable_principal_amount = args.payable_principal
+	loan_interest_accrual.accrual_type = args.accrual_type
 
 	loan_interest_accrual.save()
 	loan_interest_accrual.submit()
 
 
 def get_no_of_days_for_interest_accural(loan, posting_date):
-	last_interest_accrual_date = get_last_accural_date_in_current_month(loan)
+	last_interest_accrual_date = get_last_accural_date(loan.name)
 
 	no_of_days = date_diff(posting_date or nowdate(), last_interest_accrual_date) + 1
 
 	return no_of_days
 
-def get_last_accural_date_in_current_month(loan):
+def get_last_accural_date(loan):
 	last_posting_date = frappe.db.sql(""" SELECT MAX(posting_date) from `tabLoan Interest Accrual`
-		WHERE loan = %s""", (loan.name))
+		WHERE loan = %s""", (loan))
 
 	if last_posting_date[0][0]:
 		# interest for last interest accrual date is already booked, so add 1 day
 		return add_days(last_posting_date[0][0], 1)
 	else:
-		return loan.disbursement_date
+		return frappe.db.get_value('Loan', loan, 'disbursement_date')
 
 def days_in_year(year):
 	days = 365
@@ -226,3 +234,11 @@
 
 	return days
 
+def get_per_day_interest(principal_amount, rate_of_interest, posting_date=None):
+	if not posting_date:
+		posting_date = getdate()
+
+	precision = cint(frappe.db.get_default("currency_precision")) or 2
+
+	return flt((principal_amount * rate_of_interest) / (days_in_year(get_datetime(posting_date).year) * 100), precision)
+
diff --git a/erpnext/loan_management/doctype/loan_interest_accrual/test_loan_interest_accrual.py b/erpnext/loan_management/doctype/loan_interest_accrual/test_loan_interest_accrual.py
index 4b85b21..46a6440 100644
--- a/erpnext/loan_management/doctype/loan_interest_accrual/test_loan_interest_accrual.py
+++ b/erpnext/loan_management/doctype/loan_interest_accrual/test_loan_interest_accrual.py
@@ -5,7 +5,7 @@
 import frappe
 import unittest
 from frappe.utils import (nowdate, add_days, get_datetime, get_first_day, get_last_day, date_diff, flt, add_to_date)
-from erpnext.loan_management.doctype.loan.test_loan import (create_loan_type, create_loan_security_pledge, create_loan_security_price,
+from erpnext.loan_management.doctype.loan.test_loan import (create_loan_type, create_loan_security_price,
 	make_loan_disbursement_entry, create_loan_accounts, create_loan_security_type, create_loan_security, create_demand_loan, create_loan_application)
 from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import process_loan_interest_accrual_for_demand_loans
 from erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual import days_in_year
@@ -57,4 +57,4 @@
 
 		loan_interest_accural = frappe.get_doc("Loan Interest Accrual", {'loan': loan.name})
 
-		self.assertEquals(flt(loan_interest_accural.interest_amount, 2), flt(accrued_interest_amount, 2))
+		self.assertEquals(flt(loan_interest_accural.interest_amount, 0), flt(accrued_interest_amount, 0))
diff --git a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.json b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.json
index 5942455..60b2036 100644
--- a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.json
+++ b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.json
@@ -10,11 +10,11 @@
   "applicant_type",
   "applicant",
   "loan_type",
-  "payment_type",
   "column_break_3",
   "company",
   "posting_date",
   "is_term_loan",
+  "rate_of_interest",
   "payment_details_section",
   "due_date",
   "pending_principal_amount",
@@ -31,6 +31,7 @@
   "column_break_21",
   "reference_date",
   "principal_amount_paid",
+  "total_interest_paid",
   "repayment_details",
   "amended_from"
  ],
@@ -96,15 +97,6 @@
    "fieldtype": "Column Break"
   },
   {
-   "default": "Regular Payment",
-   "fieldname": "payment_type",
-   "fieldtype": "Select",
-   "in_list_view": 1,
-   "label": "Payment Type",
-   "options": "\nRegular Payment\nLoan Closure",
-   "reqd": 1
-  },
-  {
    "fieldname": "payable_amount",
    "fieldtype": "Currency",
    "label": "Payable Amount",
@@ -195,6 +187,7 @@
    "fieldtype": "Currency",
    "hidden": 1,
    "label": "Principal Amount Paid",
+   "options": "Company:company:default_currency",
    "read_only": 1
   },
   {
@@ -217,11 +210,27 @@
    "hidden": 1,
    "label": "Repayment Details",
    "options": "Loan Repayment Detail"
+  },
+  {
+   "fieldname": "total_interest_paid",
+   "fieldtype": "Currency",
+   "hidden": 1,
+   "label": "Total Interest Paid",
+   "options": "Company:company:default_currency",
+   "read_only": 1
+  },
+  {
+   "fetch_from": "loan_type.rate_of_interest",
+   "fieldname": "rate_of_interest",
+   "fieldtype": "Percent",
+   "label": "Rate Of Interest",
+   "read_only": 1
   }
  ],
+ "index_web_pages_for_search": 1,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-05-16 09:40:15.581165",
+ "modified": "2020-10-10 03:49:01.827593",
  "modified_by": "Administrator",
  "module": "Loan Management",
  "name": "Loan Repayment",
diff --git a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py
index 97dbc44..12d81d3 100644
--- a/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py
+++ b/erpnext/loan_management/doctype/loan_repayment/loan_repayment.py
@@ -14,26 +14,25 @@
 from erpnext.accounts.general_ledger import make_gl_entries
 from erpnext.loan_management.doctype.loan_security_shortfall.loan_security_shortfall import update_shortfall_status
 from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import process_loan_interest_accrual_for_demand_loans
+from erpnext.loan_management.doctype.loan_interest_accrual.loan_interest_accrual import get_per_day_interest, get_last_accural_date
 
 class LoanRepayment(AccountsController):
 
 	def validate(self):
-		amounts = calculate_amounts(self.against_loan, self.posting_date, self.payment_type)
+		amounts = calculate_amounts(self.against_loan, self.posting_date)
 		self.set_missing_values(amounts)
 		self.validate_amount()
-		self.allocate_amounts(amounts['pending_accrual_entries'])
-
-	def before_submit(self):
-		self.book_unaccrued_interest()
+		self.allocate_amounts(amounts)
 
 	def on_submit(self):
+		self.book_unaccrued_interest()
 		self.update_paid_amount()
 		self.make_gl_entries()
 
 	def on_cancel(self):
 		self.mark_as_unpaid()
-		self.make_gl_entries(cancel=1)
 		self.ignore_linked_doctypes = ['GL Entry']
+		self.make_gl_entries(cancel=1)
 
 	def set_missing_values(self, amounts):
 		precision = cint(frappe.db.get_default("currency_precision")) or 2
@@ -72,29 +71,36 @@
 			msg = _("Paid amount cannot be less than {0}").format(self.penalty_amount)
 			frappe.throw(msg)
 
-		if self.payment_type == "Loan Closure" and flt(self.amount_paid, precision) < flt(self.payable_amount, precision):
-			msg = _("Amount of {0} is required for Loan closure").format(self.payable_amount)
-			frappe.throw(msg)
-
 	def book_unaccrued_interest(self):
-		if self.payment_type == 'Loan Closure':
-			total_interest_paid = 0
-			for payment in self.repayment_details:
-				total_interest_paid += payment.paid_interest_amount
+		precision = cint(frappe.db.get_default("currency_precision")) or 2
+		if self.total_interest_paid > self.interest_payable:
+			if not self.is_term_loan:
+				# get last loan interest accrual date
+				last_accrual_date = get_last_accural_date(self.against_loan)
 
-			if total_interest_paid < self.interest_payable:
-				if not self.is_term_loan:
-					process = process_loan_interest_accrual_for_demand_loans(posting_date=self.posting_date,
-						loan=self.against_loan)
+				# get posting date upto which interest has to be accrued
+				per_day_interest = flt(get_per_day_interest(self.pending_principal_amount,
+					self.rate_of_interest, self.posting_date), 2)
 
-					lia = frappe.db.get_value('Loan Interest Accrual', {'process_loan_interest_accrual':
-						process}, ['name', 'interest_amount', 'payable_principal_amount'], as_dict=1)
+				no_of_days = flt(flt(self.total_interest_paid - self.interest_payable,
+					precision)/per_day_interest, 0) - 1
 
-					self.append('repayment_details', {
-						'loan_interest_accrual': lia.name,
-						'paid_interest_amount': lia.interest_amount,
-						'paid_principal_amount': lia.payable_principal_amount
-					})
+
+				posting_date = add_days(last_accrual_date, no_of_days)
+
+				# book excess interest paid
+				process = process_loan_interest_accrual_for_demand_loans(posting_date=posting_date,
+					loan=self.against_loan, accrual_type="Repayment")
+
+				# get loan interest accrual to update paid amount
+				lia = frappe.db.get_value('Loan Interest Accrual', {'process_loan_interest_accrual':
+					process}, ['name', 'interest_amount', 'payable_principal_amount'], as_dict=1)
+
+				self.append('repayment_details', {
+					'loan_interest_accrual': lia.name,
+					'paid_interest_amount': flt(self.total_interest_paid - self.interest_payable, precision),
+					'paid_principal_amount': 0.0
+				})
 
 	def update_paid_amount(self):
 		precision = cint(frappe.db.get_default("currency_precision")) or 2
@@ -108,12 +114,6 @@
 				WHERE name = %s""",
 				(flt(payment.paid_principal_amount, precision), flt(payment.paid_interest_amount, precision), payment.loan_interest_accrual))
 
-		if flt(loan.total_principal_paid + self.principal_amount_paid, precision) >= flt(loan.total_payment, precision):
-			if loan.is_secured_loan:
-				frappe.db.set_value("Loan", self.against_loan, "status", "Loan Closure Requested")
-			else:
-				frappe.db.set_value("Loan", self.against_loan, "status", "Closed")
-
 		frappe.db.sql(""" UPDATE `tabLoan` SET total_amount_paid = %s, total_principal_paid = %s
 			WHERE name = %s """, (loan.total_amount_paid + self.amount_paid,
 			loan.total_principal_paid + self.principal_amount_paid, self.against_loan))
@@ -137,15 +137,17 @@
 		if loan.status == "Loan Closure Requested":
 			frappe.db.set_value("Loan", self.against_loan, "status", "Disbursed")
 
-	def allocate_amounts(self, paid_entries):
+	def allocate_amounts(self, repayment_details):
+		precision = cint(frappe.db.get_default("currency_precision")) or 2
+
 		self.set('repayment_details', [])
 		self.principal_amount_paid = 0
 		total_interest_paid = 0
 		interest_paid = self.amount_paid - self.penalty_amount
 
-		if self.amount_paid - self.penalty_amount > 0 and paid_entries:
+		if self.amount_paid - self.penalty_amount > 0:
 			interest_paid = self.amount_paid - self.penalty_amount
-			for lia, amounts in iteritems(paid_entries):
+			for lia, amounts in iteritems(repayment_details.get('pending_accrual_entries', [])):
 				if amounts['interest_amount'] + amounts['payable_principal_amount'] <= interest_paid:
 					interest_amount = amounts['interest_amount']
 					paid_principal = amounts['payable_principal_amount']
@@ -169,9 +171,24 @@
 					'paid_principal_amount': paid_principal
 				})
 
-		if self.payment_type == 'Loan Closure' and total_interest_paid < self.interest_payable:
-			unaccrued_interest = self.interest_payable - total_interest_paid
-			interest_paid -= unaccrued_interest
+		if repayment_details['unaccrued_interest'] and interest_paid:
+			# no of days for which to accrue interest
+			# Interest can only be accrued for an entire day and not partial
+			if interest_paid > repayment_details['unaccrued_interest']:
+				per_day_interest = flt(get_per_day_interest(self.pending_principal_amount,
+					self.rate_of_interest, self.posting_date), precision)
+				interest_paid -= repayment_details['unaccrued_interest']
+				total_interest_paid += repayment_details['unaccrued_interest']
+			else:
+				# get no of days for which interest can be paid
+				per_day_interest = flt(get_per_day_interest(self.pending_principal_amount,
+					self.rate_of_interest, self.posting_date), precision)
+
+				no_of_days = cint(interest_paid/per_day_interest)
+				total_interest_paid += no_of_days * per_day_interest
+				interest_paid -= no_of_days * per_day_interest
+
+		self.total_interest_paid = total_interest_paid
 
 		if interest_paid:
 			self.principal_amount_paid += interest_paid
@@ -219,7 +236,7 @@
 				"against": loan_details.loan_account + ", " + loan_details.interest_income_account
 						+ ", " + loan_details.penalty_income_account,
 				"debit": self.amount_paid,
-				"debit_in_account_currency": self.amount_paid ,
+				"debit_in_account_currency": self.amount_paid,
 				"against_voucher_type": "Loan",
 				"against_voucher": self.against_loan,
 				"remarks": _("Against Loan:") + self.against_loan,
@@ -289,7 +306,7 @@
 # This function returns the amounts that are payable at the time of loan repayment based on posting date
 # So it pulls all the unpaid Loan Interest Accrual Entries and calculates the penalty if applicable
 
-def get_amounts(amounts, against_loan, posting_date, payment_type):
+def get_amounts(amounts, against_loan, posting_date):
 	precision = cint(frappe.db.get_default("currency_precision")) or 2
 
 	against_loan_doc = frappe.get_doc("Loan", against_loan)
@@ -328,19 +345,22 @@
 			final_due_date = add_days(due_date, loan_type_details.grace_period_in_days)
 
 	if against_loan_doc.status in ('Disbursed', 'Loan Closure Requested', 'Closed'):
-		pending_principal_amount = against_loan_doc.total_payment - against_loan_doc.total_principal_paid - against_loan_doc.total_interest_payable
+		pending_principal_amount = against_loan_doc.total_payment - against_loan_doc.total_principal_paid \
+			- against_loan_doc.total_interest_payable - against_loan_doc.written_off_amount
 	else:
-		pending_principal_amount = against_loan_doc.disbursed_amount
+		pending_principal_amount = against_loan_doc.disbursed_amount - against_loan_doc.total_principal_paid \
+			- against_loan_doc.total_interest_payable - against_loan_doc.written_off_amount
 
-	if payment_type == "Loan Closure":
-		if due_date:
-			pending_days = date_diff(posting_date, due_date) + 1
-		else:
-			pending_days = date_diff(posting_date, against_loan_doc.disbursement_date) + 1
+	unaccrued_interest = 0
+	if due_date:
+		pending_days = date_diff(posting_date, due_date) + 1
+	else:
+		pending_days = date_diff(posting_date, against_loan_doc.disbursement_date) + 1
 
-		payable_principal_amount = pending_principal_amount
-		per_day_interest = (payable_principal_amount * (loan_type_details.rate_of_interest / 100))/365
-		total_pending_interest += (pending_days * per_day_interest)
+	if pending_days > 0:
+		principal_amount = flt(pending_principal_amount, precision)
+		per_day_interest = get_per_day_interest(principal_amount, loan_type_details.rate_of_interest, posting_date)
+		unaccrued_interest += (pending_days * flt(per_day_interest, precision))
 
 	amounts["pending_principal_amount"] = flt(pending_principal_amount, precision)
 	amounts["payable_principal_amount"] = flt(payable_principal_amount, precision)
@@ -348,6 +368,7 @@
 	amounts["penalty_amount"] = flt(penalty_amount, precision)
 	amounts["payable_amount"] = flt(payable_principal_amount + total_pending_interest + penalty_amount, precision)
 	amounts["pending_accrual_entries"] = pending_accrual_entries
+	amounts["unaccrued_interest"] = unaccrued_interest
 
 	if final_due_date:
 		amounts["due_date"] = final_due_date
@@ -355,7 +376,7 @@
 	return amounts
 
 @frappe.whitelist()
-def calculate_amounts(against_loan, posting_date, payment_type):
+def calculate_amounts(against_loan, posting_date, payment_type=''):
 
 	amounts = {
 		'penalty_amount': 0.0,
@@ -363,10 +384,17 @@
 		'pending_principal_amount': 0.0,
 		'payable_principal_amount': 0.0,
 		'payable_amount': 0.0,
+		'unaccrued_interest': 0.0,
 		'due_date': ''
 	}
 
-	amounts = get_amounts(amounts, against_loan, posting_date, payment_type)
+	amounts = get_amounts(amounts, against_loan, posting_date)
+
+	# update values for closure
+	if payment_type == 'Loan Closure':
+		amounts['payable_principal_amount'] = amounts['pending_principal_amount']
+		amounts['interest_amount'] += amounts['unaccrued_interest']
+		amounts['payable_amount'] = amounts['payable_principal_amount'] + amounts['interest_amount']
 
 	return amounts
 
diff --git a/erpnext/loan_management/doctype/loan_security_pledge/loan_security_pledge.py b/erpnext/loan_management/doctype/loan_security_pledge/loan_security_pledge.py
index 2bb6fd8..cbc8376 100644
--- a/erpnext/loan_management/doctype/loan_security_pledge/loan_security_pledge.py
+++ b/erpnext/loan_management/doctype/loan_security_pledge/loan_security_pledge.py
@@ -78,7 +78,7 @@
 		self.maximum_loan_value = maximum_loan_value
 
 def update_loan(loan, maximum_value_against_pledge):
-	maximum_loan_value = frappe.db.get_value('Loan', {'name': loan}, ['maximum_loan_value'])
+	maximum_loan_value = frappe.db.get_value('Loan', {'name': loan}, ['maximum_loan_amount'])
 
-	frappe.db.sql(""" UPDATE `tabLoan` SET maximum_loan_value=%s, is_secured_loan=1
+	frappe.db.sql(""" UPDATE `tabLoan` SET maximum_loan_amount=%s, is_secured_loan=1
 		WHERE name=%s""", (maximum_loan_value + maximum_value_against_pledge, loan))
diff --git a/erpnext/loan_management/doctype/loan_security_unpledge/loan_security_unpledge.py b/erpnext/loan_management/doctype/loan_security_unpledge/loan_security_unpledge.py
index b3eb600..d0d25e8 100644
--- a/erpnext/loan_management/doctype/loan_security_unpledge/loan_security_unpledge.py
+++ b/erpnext/loan_management/doctype/loan_security_unpledge/loan_security_unpledge.py
@@ -42,10 +42,10 @@
 				"valid_upto": (">=", get_datetime())
 			}, as_list=1))
 
-		total_payment, principal_paid, interest_payable = frappe.get_value("Loan", self.loan, ['total_payment', 'total_principal_paid',
-			'total_interest_payable'])
+		total_payment, principal_paid, interest_payable, written_off_amount = frappe.get_value("Loan", self.loan, ['total_payment', 'total_principal_paid',
+			'total_interest_payable', 'written_off_amount'])
 
-		pending_principal_amount = flt(total_payment) - flt(interest_payable) - flt(principal_paid)
+		pending_principal_amount = flt(total_payment) - flt(interest_payable) - flt(principal_paid) - flt(written_off_amount)
 		security_value = 0
 
 		for security in self.securities:
diff --git a/erpnext/loan_management/doctype/loan_type/loan_type.json b/erpnext/loan_management/doctype/loan_type/loan_type.json
index 669490a..5d9232d 100644
--- a/erpnext/loan_management/doctype/loan_type/loan_type.json
+++ b/erpnext/loan_management/doctype/loan_type/loan_type.json
@@ -11,6 +11,7 @@
   "rate_of_interest",
   "penalty_interest_rate",
   "grace_period_in_days",
+  "write_off_amount",
   "column_break_2",
   "company",
   "is_term_loan",
@@ -76,7 +77,6 @@
    "reqd": 1
   },
   {
-   "description": "This account is used for booking loan repayments from the borrower and also disbursing loans to the borrower",
    "fieldname": "payment_account",
    "fieldtype": "Link",
    "label": "Payment Account",
@@ -84,7 +84,6 @@
    "reqd": 1
   },
   {
-   "description": "This account is capital account which is used to allocate capital for loan disbursal account ",
    "fieldname": "loan_account",
    "fieldtype": "Link",
    "label": "Loan Account",
@@ -96,7 +95,6 @@
    "fieldtype": "Column Break"
   },
   {
-   "description": "This account will be used for booking loan interest accruals",
    "fieldname": "interest_income_account",
    "fieldtype": "Link",
    "label": "Interest Income Account",
@@ -104,7 +102,6 @@
    "reqd": 1
   },
   {
-   "description": "This account will be used for booking penalties levied due to delayed repayments",
    "fieldname": "penalty_income_account",
    "fieldtype": "Link",
    "label": "Penalty Income Account",
@@ -113,7 +110,6 @@
   },
   {
    "default": "0",
-   "description": "If this is not checked the loan by default will be considered as a Demand Loan",
    "fieldname": "is_term_loan",
    "fieldtype": "Check",
    "label": "Is Term Loan"
@@ -145,11 +141,20 @@
    "label": "Company",
    "options": "Company",
    "reqd": 1
+  },
+  {
+   "allow_on_submit": 1,
+   "description": "Pending amount that will be automatically ignored on loan closure request ",
+   "fieldname": "write_off_amount",
+   "fieldtype": "Currency",
+   "label": "Write Off Amount ",
+   "options": "Company:company:default_currency"
   }
  ],
+ "index_web_pages_for_search": 1,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-06-07 18:55:59.346292",
+ "modified": "2020-10-17 11:41:17.907683",
  "modified_by": "Administrator",
  "module": "Loan Management",
  "name": "Loan Type",
diff --git a/erpnext/loan_management/doctype/loan_write_off/__init__.py b/erpnext/loan_management/doctype/loan_write_off/__init__.py
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/erpnext/loan_management/doctype/loan_write_off/__init__.py
diff --git a/erpnext/loan_management/doctype/loan_write_off/loan_write_off.js b/erpnext/loan_management/doctype/loan_write_off/loan_write_off.js
new file mode 100644
index 0000000..cc5cd0d
--- /dev/null
+++ b/erpnext/loan_management/doctype/loan_write_off/loan_write_off.js
@@ -0,0 +1,18 @@
+// Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+// For license information, please see license.txt
+
+{% include 'erpnext/loan_management/loan_common.js' %};
+
+frappe.ui.form.on('Loan Write Off', {
+	refresh: function(frm) {
+		frm.set_query('write_off_account', function(){
+			return {
+				filters: {
+					'company': frm.doc.company,
+					'root_type': 'Expense',
+					'is_group': 0
+				}
+			}
+		});
+	}
+});
diff --git a/erpnext/loan_management/doctype/loan_write_off/loan_write_off.json b/erpnext/loan_management/doctype/loan_write_off/loan_write_off.json
new file mode 100644
index 0000000..64623c4
--- /dev/null
+++ b/erpnext/loan_management/doctype/loan_write_off/loan_write_off.json
@@ -0,0 +1,141 @@
+{
+ "actions": [],
+ "autoname": "LM-WO-.#####",
+ "creation": "2020-10-16 11:09:14.495066",
+ "doctype": "DocType",
+ "editable_grid": 1,
+ "engine": "InnoDB",
+ "field_order": [
+  "loan",
+  "applicant_type",
+  "applicant",
+  "column_break_3",
+  "company",
+  "posting_date",
+  "accounting_dimensions_section",
+  "cost_center",
+  "section_break_9",
+  "write_off_account",
+  "column_break_11",
+  "write_off_amount",
+  "amended_from"
+ ],
+ "fields": [
+  {
+   "fieldname": "loan",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Loan",
+   "options": "Loan",
+   "reqd": 1
+  },
+  {
+   "default": "Today",
+   "fieldname": "posting_date",
+   "fieldtype": "Date",
+   "in_list_view": 1,
+   "label": "Posting Date",
+   "reqd": 1
+  },
+  {
+   "fieldname": "column_break_3",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fetch_from": "loan.company",
+   "fieldname": "company",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Company",
+   "options": "Company",
+   "read_only": 1,
+   "reqd": 1
+  },
+  {
+   "fetch_from": "loan.applicant_type",
+   "fieldname": "applicant_type",
+   "fieldtype": "Select",
+   "label": "Applicant Type",
+   "options": "Employee\nMember\nCustomer",
+   "read_only": 1
+  },
+  {
+   "fetch_from": "loan.applicant",
+   "fieldname": "applicant",
+   "fieldtype": "Dynamic Link",
+   "label": "Applicant ",
+   "options": "applicant_type",
+   "read_only": 1
+  },
+  {
+   "collapsible": 1,
+   "fieldname": "accounting_dimensions_section",
+   "fieldtype": "Section Break",
+   "label": "Accounting Dimensions"
+  },
+  {
+   "fieldname": "cost_center",
+   "fieldtype": "Link",
+   "label": "Cost Center",
+   "options": "Cost Center"
+  },
+  {
+   "fieldname": "section_break_9",
+   "fieldtype": "Section Break",
+   "label": "Write Off Details"
+  },
+  {
+   "fieldname": "write_off_account",
+   "fieldtype": "Link",
+   "in_list_view": 1,
+   "label": "Write Off Account",
+   "options": "Account",
+   "reqd": 1
+  },
+  {
+   "fieldname": "write_off_amount",
+   "fieldtype": "Currency",
+   "label": "Write Off Amount",
+   "options": "Company:company:default_currency",
+   "reqd": 1
+  },
+  {
+   "fieldname": "column_break_11",
+   "fieldtype": "Column Break"
+  },
+  {
+   "fieldname": "amended_from",
+   "fieldtype": "Link",
+   "label": "Amended From",
+   "no_copy": 1,
+   "options": "Loan Write Off",
+   "print_hide": 1,
+   "read_only": 1
+  }
+ ],
+ "index_web_pages_for_search": 1,
+ "is_submittable": 1,
+ "links": [],
+ "modified": "2020-10-17 08:30:54.859362",
+ "modified_by": "Administrator",
+ "module": "Loan Management",
+ "name": "Loan Write Off",
+ "owner": "Administrator",
+ "permissions": [
+  {
+   "create": 1,
+   "delete": 1,
+   "email": 1,
+   "export": 1,
+   "print": 1,
+   "read": 1,
+   "report": 1,
+   "role": "System Manager",
+   "share": 1,
+   "write": 1
+  }
+ ],
+ "sort_field": "modified",
+ "sort_order": "DESC",
+ "track_changes": 1
+}
\ No newline at end of file
diff --git a/erpnext/loan_management/doctype/loan_write_off/loan_write_off.py b/erpnext/loan_management/doctype/loan_write_off/loan_write_off.py
new file mode 100644
index 0000000..823e6a9
--- /dev/null
+++ b/erpnext/loan_management/doctype/loan_write_off/loan_write_off.py
@@ -0,0 +1,88 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and contributors
+# For license information, please see license.txt
+
+from __future__ import unicode_literals
+import frappe, erpnext
+from frappe import _
+from frappe.utils import getdate, flt
+from erpnext.controllers.accounts_controller import AccountsController
+from erpnext.accounts.general_ledger import make_gl_entries
+
+class LoanWriteOff(AccountsController):
+	def validate(self):
+		self.set_missing_values()
+		self.validate_write_off_amount()
+
+	def set_missing_values(self):
+		if not self.cost_center:
+			self.cost_center = erpnext.get_default_cost_center(self.company)
+
+	def validate_write_off_amount(self):
+		total_payment, principal_paid, interest_payable, written_off_amount = frappe.get_value("Loan", self.loan,
+			['total_payment', 'total_principal_paid','total_interest_payable', 'written_off_amount'])
+
+		pending_principal_amount = flt(total_payment) - flt(interest_payable) - flt(principal_paid) - flt(written_off_amount)
+
+		if self.write_off_amount > pending_principal_amount:
+			frappe.throw(_("Write off amount cannot be greater than pending principal amount"))
+
+	def on_submit(self):
+		self.update_outstanding_amount()
+		self.make_gl_entries()
+
+	def on_cancel(self):
+		self.update_outstanding_amount(cancel=1)
+		self.ignore_linked_doctypes = ['GL Entry']
+		self.make_gl_entries(cancel=1)
+
+	def update_outstanding_amount(self, cancel=0):
+		written_off_amount = frappe.db.get_value('Loan', self.loan, 'written_off_amount')
+
+		if cancel:
+			written_off_amount -= self.write_off_amount
+		else:
+			written_off_amount += self.write_off_amount
+
+		frappe.db.set_value('Loan', self.loan, 'written_off_amount', written_off_amount)
+
+
+	def make_gl_entries(self, cancel=0):
+		gl_entries = []
+		loan_details = frappe.get_doc("Loan", self.loan)
+
+		gl_entries.append(
+			self.get_gl_dict({
+				"account": self.write_off_account,
+				"against": loan_details.loan_account,
+				"debit": self.write_off_amount,
+				"debit_in_account_currency": self.write_off_amount,
+				"against_voucher_type": "Loan",
+				"against_voucher": self.loan,
+				"remarks": _("Against Loan:") + self.loan,
+				"cost_center": self.cost_center,
+				"party_type": self.applicant_type,
+				"party": self.applicant,
+				"posting_date": getdate(self.posting_date)
+			})
+		)
+
+		gl_entries.append(
+			self.get_gl_dict({
+				"account": loan_details.loan_account,
+				"party_type": loan_details.applicant_type,
+				"party": loan_details.applicant,
+				"against": self.write_off_account,
+				"credit": self.write_off_amount,
+				"credit_in_account_currency": self.write_off_amount,
+				"against_voucher_type": "Loan",
+				"against_voucher": self.loan,
+				"remarks": _("Against Loan:") + self.loan,
+				"cost_center": self.cost_center,
+				"posting_date": getdate(self.posting_date)
+			})
+		)
+
+		make_gl_entries(gl_entries, cancel=cancel, merge_entries=False)
+
+
diff --git a/erpnext/loan_management/doctype/loan_write_off/test_loan_write_off.py b/erpnext/loan_management/doctype/loan_write_off/test_loan_write_off.py
new file mode 100644
index 0000000..9f6700e
--- /dev/null
+++ b/erpnext/loan_management/doctype/loan_write_off/test_loan_write_off.py
@@ -0,0 +1,10 @@
+# -*- coding: utf-8 -*-
+# Copyright (c) 2020, Frappe Technologies Pvt. Ltd. and Contributors
+# See license.txt
+from __future__ import unicode_literals
+
+# import frappe
+import unittest
+
+class TestLoanWriteOff(unittest.TestCase):
+	pass
diff --git a/erpnext/loan_management/doctype/process_loan_interest_accrual/process_loan_interest_accrual.json b/erpnext/loan_management/doctype/process_loan_interest_accrual/process_loan_interest_accrual.json
index 0ef098f..bb781b1 100644
--- a/erpnext/loan_management/doctype/process_loan_interest_accrual/process_loan_interest_accrual.json
+++ b/erpnext/loan_management/doctype/process_loan_interest_accrual/process_loan_interest_accrual.json
@@ -10,6 +10,7 @@
   "loan_type",
   "loan",
   "process_type",
+  "accrual_type",
   "amended_from"
  ],
  "fields": [
@@ -47,11 +48,18 @@
    "hidden": 1,
    "label": "Process Type",
    "read_only": 1
+  },
+  {
+   "fieldname": "accrual_type",
+   "fieldtype": "Select",
+   "label": "Accrual Type",
+   "options": "Regular\nRepayment\nDisbursement"
   }
  ],
+ "index_web_pages_for_search": 1,
  "is_submittable": 1,
  "links": [],
- "modified": "2020-04-09 22:52:53.911416",
+ "modified": "2020-10-11 11:19:00.531046",
  "modified_by": "Administrator",
  "module": "Loan Management",
  "name": "Process Loan Interest Accrual",
diff --git a/erpnext/loan_management/doctype/process_loan_interest_accrual/process_loan_interest_accrual.py b/erpnext/loan_management/doctype/process_loan_interest_accrual/process_loan_interest_accrual.py
index 0fa9686..1eeb18b 100644
--- a/erpnext/loan_management/doctype/process_loan_interest_accrual/process_loan_interest_accrual.py
+++ b/erpnext/loan_management/doctype/process_loan_interest_accrual/process_loan_interest_accrual.py
@@ -20,19 +20,20 @@
 
 		if (not self.loan or not loan_doc.is_term_loan) and self.process_type != 'Term Loans':
 			make_accrual_interest_entry_for_demand_loans(self.posting_date, self.name,
-				open_loans = open_loans, loan_type = self.loan_type)
+				open_loans = open_loans, loan_type = self.loan_type, accrual_type=self.accrual_type)
 
 		if (not self.loan or loan_doc.is_term_loan) and self.process_type != 'Demand Loans':
 			make_accrual_interest_entry_for_term_loans(self.posting_date, self.name, term_loan=self.loan,
 				loan_type=self.loan_type)
 
 
-def process_loan_interest_accrual_for_demand_loans(posting_date=None, loan_type=None, loan=None):
+def process_loan_interest_accrual_for_demand_loans(posting_date=None, loan_type=None, loan=None, accrual_type="Regular"):
 	loan_process = frappe.new_doc('Process Loan Interest Accrual')
 	loan_process.posting_date = posting_date or nowdate()
 	loan_process.loan_type = loan_type
 	loan_process.process_type = 'Demand Loans'
 	loan_process.loan = loan
+	loan_process.accrual_type = accrual_type
 
 	loan_process.submit()
 
diff --git a/erpnext/loan_management/loan_common.js b/erpnext/loan_management/loan_common.js
index d9dd415..50b68da 100644
--- a/erpnext/loan_management/loan_common.js
+++ b/erpnext/loan_management/loan_common.js
@@ -8,14 +8,14 @@
 			frm.refresh_field('applicant_type');
 		}
 
-		if (['Loan Disbursement', 'Loan Repayment', 'Loan Interest Accrual'].includes(frm.doc.doctype)
+		if (['Loan Disbursement', 'Loan Repayment', 'Loan Interest Accrual', 'Loan Write Off'].includes(frm.doc.doctype)
 			&& frm.doc.docstatus > 0) {
 
 			frm.add_custom_button(__("Accounting Ledger"), function() {
 				frappe.route_options = {
 					voucher_no: frm.doc.name,
 					company: frm.doc.company,
-					from_date: frm.doc.posting_date,
+					from_date: moment(frm.doc.posting_date).format('YYYY-MM-DD'),
 					to_date: moment(frm.doc.modified).format('YYYY-MM-DD'),
 					show_cancelled_entries: frm.doc.docstatus === 2
 				};