Merge pull request #29460 from deepeshgarg007/loan_refund_jv
feat: Refund entry against loans
diff --git a/erpnext/loan_management/doctype/loan/loan.js b/erpnext/loan_management/doctype/loan/loan.js
index f9c201a..940a1bb 100644
--- a/erpnext/loan_management/doctype/loan/loan.js
+++ b/erpnext/loan_management/doctype/loan/loan.js
@@ -46,7 +46,7 @@
});
});
- $.each(["payment_account", "loan_account"], function (i, field) {
+ $.each(["payment_account", "loan_account", "disbursement_account"], function (i, field) {
frm.set_query(field, function () {
return {
"filters": {
@@ -88,6 +88,10 @@
frm.add_custom_button(__('Loan Write Off'), function() {
frm.trigger("make_loan_write_off_entry");
},__('Create'));
+
+ frm.add_custom_button(__('Loan Refund'), function() {
+ frm.trigger("make_loan_refund");
+ },__('Create'));
}
}
frm.trigger("toggle_fields");
@@ -155,6 +159,21 @@
})
},
+ make_loan_refund: function(frm) {
+ frappe.call({
+ args: {
+ "loan": frm.doc.name
+ },
+ method: "erpnext.loan_management.doctype.loan.loan.make_refund_jv",
+ callback: function (r) {
+ if (r.message) {
+ let 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() {
diff --git a/erpnext/loan_management/doctype/loan/loan.json b/erpnext/loan_management/doctype/loan/loan.json
index af26f7b..196f36f 100644
--- a/erpnext/loan_management/doctype/loan/loan.json
+++ b/erpnext/loan_management/doctype/loan/loan.json
@@ -2,7 +2,7 @@
"actions": [],
"allow_import": 1,
"autoname": "ACC-LOAN-.YYYY.-.#####",
- "creation": "2019-08-29 17:29:18.176786",
+ "creation": "2022-01-25 10:30:02.294967",
"doctype": "DocType",
"document_type": "Document",
"editable_grid": 1,
@@ -34,6 +34,7 @@
"is_term_loan",
"account_info",
"mode_of_payment",
+ "disbursement_account",
"payment_account",
"column_break_9",
"loan_account",
@@ -356,12 +357,21 @@
"fieldtype": "Date",
"label": "Closure Date",
"read_only": 1
+ },
+ {
+ "fetch_from": "loan_type.disbursement_account",
+ "fieldname": "disbursement_account",
+ "fieldtype": "Link",
+ "label": "Disbursement Account",
+ "options": "Account",
+ "read_only": 1,
+ "reqd": 1
}
],
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
- "modified": "2021-10-12 18:10:32.360818",
+ "modified": "2022-01-25 16:29:16.325501",
"modified_by": "Administrator",
"module": "Loan Management",
"name": "Loan",
@@ -391,5 +401,6 @@
"search_fields": "posting_date",
"sort_field": "creation",
"sort_order": "DESC",
+ "states": [],
"track_changes": 1
}
\ No newline at end of file
diff --git a/erpnext/loan_management/doctype/loan/loan.py b/erpnext/loan_management/doctype/loan/loan.py
index f660a24..b798e08 100644
--- a/erpnext/loan_management/doctype/loan/loan.py
+++ b/erpnext/loan_management/doctype/loan/loan.py
@@ -10,6 +10,7 @@
from frappe.utils import add_months, flt, get_last_day, getdate, now_datetime, nowdate
import erpnext
+from erpnext.accounts.doctype.journal_entry.journal_entry import get_payment_entry
from erpnext.controllers.accounts_controller import AccountsController
from erpnext.loan_management.doctype.loan_repayment.loan_repayment import calculate_amounts
from erpnext.loan_management.doctype.loan_security_unpledge.loan_security_unpledge import (
@@ -233,17 +234,15 @@
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 not pending_amount:
- frappe.db.set_value('Loan', loan, 'status', 'Loan Closure Requested')
- elif pending_amount < write_off_limit:
+ if pending_amount and abs(pending_amount) < write_off_limit:
# Auto create loan write off and update status as loan closure requested
write_off = make_loan_write_off(loan)
write_off.submit()
- frappe.db.set_value('Loan', loan, 'status', 'Loan Closure Requested')
- else:
+ elif pending_amount > 0:
frappe.throw(_("Cannot close loan as there is an outstanding of {0}").format(pending_amount))
+ frappe.db.set_value('Loan', loan, 'status', 'Loan Closure Requested')
+
@frappe.whitelist()
def get_loan_application(loan_application):
loan = frappe.get_doc("Loan Application", loan_application)
@@ -400,4 +399,39 @@
if getdate(date) == get_last_day(date):
return get_last_day(add_months(date, 1))
else:
- return add_months(date, 1)
\ No newline at end of file
+ return add_months(date, 1)
+
+@frappe.whitelist()
+def make_refund_jv(loan, amount=0, reference_number=None, reference_date=None, submit=0):
+ loan_details = frappe.db.get_value('Loan', loan, ['applicant_type', 'applicant',
+ 'loan_account', 'payment_account', 'posting_date', 'company', 'name',
+ 'total_payment', 'total_principal_paid'], as_dict=1)
+
+ loan_details.doctype = 'Loan'
+ loan_details[loan_details.applicant_type.lower()] = loan_details.applicant
+
+ if not amount:
+ amount = flt(loan_details.total_principal_paid - loan_details.total_payment)
+
+ if amount < 0:
+ frappe.throw(_('No excess amount pending for refund'))
+
+ refund_jv = get_payment_entry(loan_details, {
+ "party_type": loan_details.applicant_type,
+ "party_account": loan_details.loan_account,
+ "amount_field_party": 'debit_in_account_currency',
+ "amount_field_bank": 'credit_in_account_currency',
+ "amount": amount,
+ "bank_account": loan_details.payment_account
+ })
+
+ if reference_number:
+ refund_jv.cheque_no = reference_number
+
+ if reference_date:
+ refund_jv.cheque_date = reference_date
+
+ if submit:
+ refund_jv.submit()
+
+ return refund_jv
\ 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 1676c21..6415689 100644
--- a/erpnext/loan_management/doctype/loan/test_loan.py
+++ b/erpnext/loan_management/doctype/loan/test_loan.py
@@ -42,16 +42,17 @@
create_loan_type("Personal Loan", 500000, 8.4,
is_term_loan=1,
mode_of_payment='Cash',
+ disbursement_account='Disbursement Account - _TC',
payment_account='Payment Account - _TC',
loan_account='Loan Account - _TC',
interest_income_account='Interest Income Account - _TC',
penalty_income_account='Penalty Income Account - _TC')
- create_loan_type("Stock Loan", 2000000, 13.5, 25, 1, 5, 'Cash', 'Payment Account - _TC', 'Loan Account - _TC',
- 'Interest Income Account - _TC', 'Penalty Income Account - _TC')
+ create_loan_type("Stock Loan", 2000000, 13.5, 25, 1, 5, 'Cash', 'Disbursement Account - _TC',
+ 'Payment Account - _TC', 'Loan Account - _TC', 'Interest Income Account - _TC', 'Penalty Income Account - _TC')
- create_loan_type("Demand Loan", 2000000, 13.5, 25, 0, 5, 'Cash', 'Payment Account - _TC', 'Loan Account - _TC',
- 'Interest Income Account - _TC', 'Penalty Income Account - _TC')
+ create_loan_type("Demand Loan", 2000000, 13.5, 25, 0, 5, 'Cash', 'Disbursement Account - _TC',
+ 'Payment Account - _TC', 'Loan Account - _TC', 'Interest Income Account - _TC', 'Penalty Income Account - _TC')
create_loan_security_type()
create_loan_security()
@@ -790,6 +791,18 @@
"account_type": "Bank",
}).insert(ignore_permissions=True)
+ if not frappe.db.exists("Account", "Disbursement Account - _TC"):
+ frappe.get_doc({
+ "doctype": "Account",
+ "company": "_Test Company",
+ "account_name": "Disbursement Account",
+ "root_type": "Asset",
+ "report_type": "Balance Sheet",
+ "currency": "INR",
+ "parent_account": "Bank Accounts - _TC",
+ "account_type": "Bank",
+ }).insert(ignore_permissions=True)
+
if not frappe.db.exists("Account", "Interest Income Account - _TC"):
frappe.get_doc({
"doctype": "Account",
@@ -815,7 +828,7 @@
}).insert(ignore_permissions=True)
def create_loan_type(loan_name, maximum_loan_amount, rate_of_interest, penalty_interest_rate=None, is_term_loan=None, grace_period_in_days=None,
- mode_of_payment=None, payment_account=None, loan_account=None, interest_income_account=None, penalty_income_account=None,
+ mode_of_payment=None, disbursement_account=None, payment_account=None, loan_account=None, interest_income_account=None, penalty_income_account=None,
repayment_method=None, repayment_periods=None):
if not frappe.db.exists("Loan Type", loan_name):
@@ -829,6 +842,7 @@
"penalty_interest_rate": penalty_interest_rate,
"grace_period_in_days": grace_period_in_days,
"mode_of_payment": mode_of_payment,
+ "disbursement_account": disbursement_account,
"payment_account": payment_account,
"loan_account": loan_account,
"interest_income_account": interest_income_account,
diff --git a/erpnext/loan_management/doctype/loan_application/test_loan_application.py b/erpnext/loan_management/doctype/loan_application/test_loan_application.py
index d367e92..640709c 100644
--- a/erpnext/loan_management/doctype/loan_application/test_loan_application.py
+++ b/erpnext/loan_management/doctype/loan_application/test_loan_application.py
@@ -15,7 +15,7 @@
class TestLoanApplication(unittest.TestCase):
def setUp(self):
create_loan_accounts()
- create_loan_type("Home Loan", 500000, 9.2, 0, 1, 0, 'Cash', 'Payment Account - _TC', 'Loan Account - _TC',
+ create_loan_type("Home Loan", 500000, 9.2, 0, 1, 0, 'Cash', 'Disbursement Account - _TC', 'Payment Account - _TC', 'Loan Account - _TC',
'Interest Income Account - _TC', 'Penalty Income Account - _TC', 'Repay Over Number of Periods', 18)
self.applicant = make_employee("kate_loan@loan.com", "_Test Company")
make_salary_structure("Test Salary Structure Loan", "Monthly", employee=self.applicant, currency='INR')
diff --git a/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py b/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py
index e2d758b..df3aadf 100644
--- a/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py
+++ b/erpnext/loan_management/doctype/loan_disbursement/loan_disbursement.py
@@ -122,7 +122,7 @@
gle_map.append(
self.get_gl_dict({
"account": loan_details.loan_account,
- "against": loan_details.payment_account,
+ "against": loan_details.disbursement_account,
"debit": self.disbursed_amount,
"debit_in_account_currency": self.disbursed_amount,
"against_voucher_type": "Loan",
@@ -137,7 +137,7 @@
gle_map.append(
self.get_gl_dict({
- "account": loan_details.payment_account,
+ "account": loan_details.disbursement_account,
"against": loan_details.loan_account,
"credit": self.disbursed_amount,
"credit_in_account_currency": self.disbursed_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 94ec84e..10be750 100644
--- a/erpnext/loan_management/doctype/loan_disbursement/test_loan_disbursement.py
+++ b/erpnext/loan_management/doctype/loan_disbursement/test_loan_disbursement.py
@@ -44,8 +44,8 @@
def setUp(self):
create_loan_accounts()
- create_loan_type("Demand Loan", 2000000, 13.5, 25, 0, 5, 'Cash', 'Payment Account - _TC', 'Loan Account - _TC',
- 'Interest Income Account - _TC', 'Penalty Income Account - _TC')
+ create_loan_type("Demand Loan", 2000000, 13.5, 25, 0, 5, 'Cash', 'Disbursement Account - _TC',
+ 'Payment Account - _TC', 'Loan Account - _TC', 'Interest Income Account - _TC', 'Penalty Income Account - _TC')
create_loan_security_type()
create_loan_security()
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 46aaaad..e8c7750 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
@@ -30,8 +30,8 @@
def setUp(self):
create_loan_accounts()
- create_loan_type("Demand Loan", 2000000, 13.5, 25, 0, 5, 'Cash', 'Payment Account - _TC', 'Loan Account - _TC',
- 'Interest Income Account - _TC', 'Penalty Income Account - _TC')
+ create_loan_type("Demand Loan", 2000000, 13.5, 25, 0, 5, 'Cash', 'Disbursement Account - _TC',
+ 'Payment Account - _TC', 'Loan Account - _TC', 'Interest Income Account - _TC', 'Penalty Income Account - _TC')
create_loan_security_type()
create_loan_security()
diff --git a/erpnext/loan_management/doctype/loan_type/loan_type.js b/erpnext/loan_management/doctype/loan_type/loan_type.js
index 04c89c4..9f9137c 100644
--- a/erpnext/loan_management/doctype/loan_type/loan_type.js
+++ b/erpnext/loan_management/doctype/loan_type/loan_type.js
@@ -15,7 +15,7 @@
});
});
- $.each(["payment_account", "loan_account"], function (i, field) {
+ $.each(["payment_account", "loan_account", "disbursement_account"], function (i, field) {
frm.set_query(field, function () {
return {
"filters": {
diff --git a/erpnext/loan_management/doctype/loan_type/loan_type.json b/erpnext/loan_management/doctype/loan_type/loan_type.json
index c0a5d2c..00337e4 100644
--- a/erpnext/loan_management/doctype/loan_type/loan_type.json
+++ b/erpnext/loan_management/doctype/loan_type/loan_type.json
@@ -19,9 +19,10 @@
"description",
"account_details_section",
"mode_of_payment",
+ "disbursement_account",
"payment_account",
- "loan_account",
"column_break_12",
+ "loan_account",
"interest_income_account",
"penalty_income_account",
"amended_from"
@@ -79,7 +80,7 @@
{
"fieldname": "payment_account",
"fieldtype": "Link",
- "label": "Payment Account",
+ "label": "Repayment Account",
"options": "Account",
"reqd": 1
},
@@ -149,15 +150,23 @@
"fieldtype": "Currency",
"label": "Auto Write Off Amount ",
"options": "Company:company:default_currency"
+ },
+ {
+ "fieldname": "disbursement_account",
+ "fieldtype": "Link",
+ "label": "Disbursement Account",
+ "options": "Account",
+ "reqd": 1
}
],
"index_web_pages_for_search": 1,
"is_submittable": 1,
"links": [],
- "modified": "2021-04-19 18:10:57.368490",
+ "modified": "2022-01-25 16:23:57.009349",
"modified_by": "Administrator",
"module": "Loan Management",
"name": "Loan Type",
+ "naming_rule": "By fieldname",
"owner": "Administrator",
"permissions": [
{
@@ -181,5 +190,6 @@
}
],
"sort_field": "modified",
- "sort_order": "DESC"
+ "sort_order": "DESC",
+ "states": []
}
\ No newline at end of file
diff --git a/erpnext/patches.txt b/erpnext/patches.txt
index eace7ca..feafecb 100644
--- a/erpnext/patches.txt
+++ b/erpnext/patches.txt
@@ -349,3 +349,4 @@
erpnext.patches.v14_0.migrate_cost_center_allocations
erpnext.patches.v13_0.convert_to_website_item_in_item_card_group_template
erpnext.patches.v13_0.shopping_cart_to_ecommerce
+erpnext.patches.v13_0.update_disbursement_account
diff --git a/erpnext/patches/v13_0/update_disbursement_account.py b/erpnext/patches/v13_0/update_disbursement_account.py
new file mode 100644
index 0000000..c56fa8f
--- /dev/null
+++ b/erpnext/patches/v13_0/update_disbursement_account.py
@@ -0,0 +1,22 @@
+import frappe
+
+
+def execute():
+
+ frappe.reload_doc("loan_management", "doctype", "loan_type")
+ frappe.reload_doc("loan_management", "doctype", "loan")
+
+ loan_type = frappe.qb.DocType("Loan Type")
+ loan = frappe.qb.DocType("Loan")
+
+ frappe.qb.update(
+ loan_type
+ ).set(
+ loan_type.disbursement_account, loan_type.payment_account
+ ).run()
+
+ frappe.qb.update(
+ loan
+ ).set(
+ loan.disbursement_account, loan.payment_account
+ ).run()
\ No newline at end of file
diff --git a/erpnext/payroll/doctype/payroll_entry/test_payroll_entry.py b/erpnext/payroll/doctype/payroll_entry/test_payroll_entry.py
index 4f097fa..5f836db 100644
--- a/erpnext/payroll/doctype/payroll_entry/test_payroll_entry.py
+++ b/erpnext/payroll/doctype/payroll_entry/test_payroll_entry.py
@@ -214,6 +214,7 @@
create_loan_type("Car Loan", 500000, 8.4,
is_term_loan=1,
mode_of_payment='Cash',
+ disbursement_account='Disbursement Account - _TC',
payment_account='Payment Account - _TC',
loan_account='Loan Account - _TC',
interest_income_account='Interest Income Account - _TC',
diff --git a/erpnext/payroll/doctype/salary_slip/test_salary_slip.py b/erpnext/payroll/doctype/salary_slip/test_salary_slip.py
index 597fd5a..30b604b 100644
--- a/erpnext/payroll/doctype/salary_slip/test_salary_slip.py
+++ b/erpnext/payroll/doctype/salary_slip/test_salary_slip.py
@@ -370,6 +370,7 @@
create_loan_type("Car Loan", 500000, 8.4,
is_term_loan=1,
mode_of_payment='Cash',
+ disbursement_account='Disbursement Account - _TC',
payment_account='Payment Account - _TC',
loan_account='Loan Account - _TC',
interest_income_account='Interest Income Account - _TC',