Merge pull request #21756 from deepeshgarg007/loan_patch_and_fixes
fix: Description for fields and patch for old loans
This commit is contained in:
commit
72fc188706
@ -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 {\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 { \"dependencies\": [\n \"Loan Type\"\n ],\n \"description\": \"Loans provided to customers and employees.\",\n \"label\": \"Loan\",\n \"name\": \"Loan\",\n \"type\": \"doctype\"\n }\n]"
|
||||
},
|
||||
{
|
||||
"hidden": 0,
|
||||
|
@ -112,16 +112,19 @@ frappe.ui.form.on('Loan Application', {
|
||||
frappe.ui.form.on("Proposed Pledge", {
|
||||
loan_security: function(frm, cdt, cdn) {
|
||||
let row = locals[cdt][cdn];
|
||||
frappe.call({
|
||||
method: "erpnext.loan_management.doctype.loan_security_price.loan_security_price.get_loan_security_price",
|
||||
args: {
|
||||
loan_security: row.loan_security
|
||||
},
|
||||
callback: function(r) {
|
||||
frappe.model.set_value(cdt, cdn, 'loan_security_price', r.message);
|
||||
frm.events.calculate_amounts(frm, cdt, cdn);
|
||||
}
|
||||
})
|
||||
|
||||
if (row.loan_security) {
|
||||
frappe.call({
|
||||
method: "erpnext.loan_management.doctype.loan_security_price.loan_security_price.get_loan_security_price",
|
||||
args: {
|
||||
loan_security: row.loan_security
|
||||
},
|
||||
callback: function(r) {
|
||||
frappe.model.set_value(cdt, cdn, 'loan_security_price', r.message);
|
||||
frm.events.calculate_amounts(frm, cdt, cdn);
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
|
||||
amount: function(frm, cdt, cdn) {
|
||||
|
@ -19,8 +19,8 @@ class LoanInterestAccrual(AccountsController):
|
||||
if not self.posting_date:
|
||||
self.posting_date = nowdate()
|
||||
|
||||
if not self.interest_amount:
|
||||
frappe.throw(_("Interest Amount is mandatory"))
|
||||
if not self.interest_amount and not self.payable_principal_amount:
|
||||
frappe.throw(_("Interest Amount or Principal Amount is mandatory"))
|
||||
|
||||
|
||||
def on_submit(self):
|
||||
@ -39,37 +39,38 @@ class LoanInterestAccrual(AccountsController):
|
||||
def make_gl_entries(self, cancel=0, adv_adj=0):
|
||||
gle_map = []
|
||||
|
||||
gle_map.append(
|
||||
self.get_gl_dict({
|
||||
"account": self.loan_account,
|
||||
"party_type": self.applicant_type,
|
||||
"party": self.applicant,
|
||||
"against": self.interest_income_account,
|
||||
"debit": self.interest_amount,
|
||||
"debit_in_account_currency": self.interest_amount,
|
||||
"against_voucher_type": "Loan",
|
||||
"against_voucher": self.loan,
|
||||
"remarks": _("Against Loan:") + self.loan,
|
||||
"cost_center": erpnext.get_default_cost_center(self.company),
|
||||
"posting_date": self.posting_date
|
||||
})
|
||||
)
|
||||
if self.interest_amount:
|
||||
gle_map.append(
|
||||
self.get_gl_dict({
|
||||
"account": self.loan_account,
|
||||
"party_type": self.applicant_type,
|
||||
"party": self.applicant,
|
||||
"against": self.interest_income_account,
|
||||
"debit": self.interest_amount,
|
||||
"debit_in_account_currency": self.interest_amount,
|
||||
"against_voucher_type": "Loan",
|
||||
"against_voucher": self.loan,
|
||||
"remarks": _("Against Loan:") + self.loan,
|
||||
"cost_center": erpnext.get_default_cost_center(self.company),
|
||||
"posting_date": self.posting_date
|
||||
})
|
||||
)
|
||||
|
||||
gle_map.append(
|
||||
self.get_gl_dict({
|
||||
"account": self.interest_income_account,
|
||||
"party_type": self.applicant_type,
|
||||
"party": self.applicant,
|
||||
"against": self.loan_account,
|
||||
"credit": self.interest_amount,
|
||||
"credit_in_account_currency": self.interest_amount,
|
||||
"against_voucher_type": "Loan",
|
||||
"against_voucher": self.loan,
|
||||
"remarks": _("Against Loan:") + self.loan,
|
||||
"cost_center": erpnext.get_default_cost_center(self.company),
|
||||
"posting_date": self.posting_date
|
||||
})
|
||||
)
|
||||
gle_map.append(
|
||||
self.get_gl_dict({
|
||||
"account": self.interest_income_account,
|
||||
"party_type": self.applicant_type,
|
||||
"party": self.applicant,
|
||||
"against": self.loan_account,
|
||||
"credit": self.interest_amount,
|
||||
"credit_in_account_currency": self.interest_amount,
|
||||
"against_voucher_type": "Loan",
|
||||
"against_voucher": self.loan,
|
||||
"remarks": _("Against Loan:") + self.loan,
|
||||
"cost_center": erpnext.get_default_cost_center(self.company),
|
||||
"posting_date": self.posting_date
|
||||
})
|
||||
)
|
||||
|
||||
if gle_map:
|
||||
make_gl_entries(gle_map, cancel=cancel, adv_adj=adv_adj)
|
||||
|
@ -173,7 +173,7 @@
|
||||
{
|
||||
"fieldname": "references_section",
|
||||
"fieldtype": "Section Break",
|
||||
"label": "References"
|
||||
"label": "Payment References"
|
||||
},
|
||||
{
|
||||
"fieldname": "reference_number",
|
||||
@ -221,7 +221,7 @@
|
||||
],
|
||||
"is_submittable": 1,
|
||||
"links": [],
|
||||
"modified": "2020-04-16 18:14:45.166754",
|
||||
"modified": "2020-05-16 09:40:15.581165",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Loan Management",
|
||||
"name": "Loan Repayment",
|
||||
|
@ -22,16 +22,19 @@ frappe.ui.form.on('Loan Security Pledge', {
|
||||
frappe.ui.form.on("Pledge", {
|
||||
loan_security: function(frm, cdt, cdn) {
|
||||
let row = locals[cdt][cdn];
|
||||
frappe.call({
|
||||
method: "erpnext.loan_management.doctype.loan_security_price.loan_security_price.get_loan_security_price",
|
||||
args: {
|
||||
loan_security: row.loan_security
|
||||
},
|
||||
callback: function(r) {
|
||||
frappe.model.set_value(cdt, cdn, 'loan_security_price', r.message);
|
||||
frm.events.calculate_amounts(frm, cdt, cdn);
|
||||
}
|
||||
});
|
||||
|
||||
if (row.loan_security) {
|
||||
frappe.call({
|
||||
method: "erpnext.loan_management.doctype.loan_security_price.loan_security_price.get_loan_security_price",
|
||||
args: {
|
||||
loan_security: row.loan_security
|
||||
},
|
||||
callback: function(r) {
|
||||
frappe.model.set_value(cdt, cdn, 'loan_security_price', r.message);
|
||||
frm.events.calculate_amounts(frm, cdt, cdn);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
qty: function(frm, cdt, cdn) {
|
||||
|
@ -29,6 +29,7 @@
|
||||
"unique": 1
|
||||
},
|
||||
{
|
||||
"description": "Haircut percentage is the percentage difference between market value of the Loan Security and the value ascribed to that Loan Security when used as collateral for that loan.",
|
||||
"fieldname": "haircut",
|
||||
"fieldtype": "Percent",
|
||||
"label": "Haircut %"
|
||||
@ -46,13 +47,14 @@
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"description": "Loan To Value Ratio expresses the ratio of the loan amount to the value of the security pledged. A loan security shortfall will be triggered if this falls below the specified value for any loan ",
|
||||
"fieldname": "loan_to_value_ratio",
|
||||
"fieldtype": "Percent",
|
||||
"label": "Loan To Value Ratio"
|
||||
}
|
||||
],
|
||||
"links": [],
|
||||
"modified": "2020-04-28 14:06:49.046177",
|
||||
"modified": "2020-05-16 09:38:45.988080",
|
||||
"modified_by": "Administrator",
|
||||
"module": "Loan Management",
|
||||
"name": "Loan Security Type",
|
||||
|
@ -76,6 +76,7 @@
|
||||
"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",
|
||||
@ -83,6 +84,7 @@
|
||||
"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",
|
||||
@ -94,6 +96,7 @@
|
||||
"fieldtype": "Column Break"
|
||||
},
|
||||
{
|
||||
"description": "This account will be used for booking loan interest accruals",
|
||||
"fieldname": "interest_income_account",
|
||||
"fieldtype": "Link",
|
||||
"label": "Interest Income Account",
|
||||
@ -101,6 +104,7 @@
|
||||
"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",
|
||||
@ -109,6 +113,7 @@
|
||||
},
|
||||
{
|
||||
"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"
|
||||
|
@ -687,6 +687,7 @@ execute:frappe.delete_doc_if_exists("Page", "appointment-analytic")
|
||||
execute:frappe.rename_doc("Desk Page", "Getting Started", "Home", force=True)
|
||||
erpnext.patches.v12_0.unset_customer_supplier_based_on_type_of_item_price
|
||||
erpnext.patches.v12_0.set_valid_till_date_in_supplier_quotation
|
||||
erpnext.patches.v13_0.update_old_loans
|
||||
erpnext.patches.v12_0.set_serial_no_status #2020-05-21
|
||||
erpnext.patches.v12_0.update_price_list_currency_in_bom
|
||||
execute:frappe.delete_doc_if_exists('Dashboard', 'Accounts')
|
||||
|
88
erpnext/patches/v13_0/update_old_loans.py
Normal file
88
erpnext/patches/v13_0/update_old_loans.py
Normal file
@ -0,0 +1,88 @@
|
||||
from __future__ import unicode_literals
|
||||
import frappe
|
||||
from frappe import _
|
||||
from frappe.utils import nowdate
|
||||
from erpnext.accounts.doctype.account.test_account import create_account
|
||||
from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_interest_accrual import process_loan_interest_accrual_for_term_loans
|
||||
from erpnext.loan_management.doctype.loan.loan import make_repayment_entry
|
||||
|
||||
def execute():
|
||||
|
||||
# Create a penalty account for loan types
|
||||
|
||||
frappe.reload_doc('loan_management', 'doctype', 'loan_type')
|
||||
frappe.reload_doc('loan_management', 'doctype', 'loan')
|
||||
frappe.reload_doc('loan_management', 'doctype', 'repayment_schedule')
|
||||
frappe.reload_doc('loan_management', 'doctype', 'process_loan_interest_accrual')
|
||||
frappe.reload_doc('loan_management', 'doctype', 'loan_repayment')
|
||||
frappe.reload_doc('loan_management', 'doctype', 'loan_repayment_detail')
|
||||
frappe.reload_doc('loan_management', 'doctype', 'loan_interest_accrual')
|
||||
frappe.reload_doc('accounts', 'doctype', 'gl_entry')
|
||||
|
||||
updated_loan_types = []
|
||||
|
||||
loans = frappe.get_all('Loan', fields=['name', 'loan_type', 'company', 'status', 'mode_of_payment',
|
||||
'applicant_type', 'applicant', 'loan_account', 'payment_account', 'interest_income_account'])
|
||||
|
||||
for loan in loans:
|
||||
# Update details in Loan Types and Loan
|
||||
loan_type_company = frappe.db.get_value('Loan Type', loan.loan_type, 'company')
|
||||
|
||||
group_income_account = frappe.get_value('Account', {'company': loan.company,
|
||||
'is_group': 1, 'root_type': 'Income', 'account_name': _('Indirect Income')})
|
||||
|
||||
if not group_income_account:
|
||||
group_income_account = frappe.get_value('Account', {'company': loan.company,
|
||||
'is_group': 1, 'root_type': 'Income'})
|
||||
|
||||
penalty_account = create_account(company=loan.company, account_type='Income Account',
|
||||
account_name='Penalty Account', parent_account=group_income_account)
|
||||
|
||||
if not loan_type_company:
|
||||
loan_type_doc = frappe.get_doc('Loan Type', loan.loan_type)
|
||||
loan_type_doc.is_term_loan = 1
|
||||
loan_type_doc.company = loan.company
|
||||
loan_type_doc.mode_of_payment = loan.mode_of_payment
|
||||
loan_type_doc.payment_account = loan.payment_account
|
||||
loan_type_doc.loan_account = loan.loan_account
|
||||
loan_type_doc.interest_income_account = loan.interest_income_account
|
||||
loan_type_doc.penalty_income_account = penalty_account
|
||||
loan_type_doc.submit()
|
||||
updated_loan_types.append(loan.loan_type)
|
||||
|
||||
if loan.loan_type in updated_loan_types:
|
||||
if loan.status == 'Fully Disbursed':
|
||||
status = 'Disbursed'
|
||||
elif loan.status == 'Repaid/Closed':
|
||||
status = 'Closed'
|
||||
else:
|
||||
status = loan.status
|
||||
|
||||
frappe.db.set_value('Loan', loan.name, {
|
||||
'is_term_loan': 1,
|
||||
'penalty_income_account': penalty_account,
|
||||
'status': status
|
||||
})
|
||||
|
||||
process_loan_interest_accrual_for_term_loans(posting_date=nowdate(), loan_type=loan.loan_type,
|
||||
loan=loan.name)
|
||||
|
||||
payments = frappe.db.sql(''' SELECT j.name, a.debit, a.debit_in_account_currency, j.posting_date
|
||||
FROM `tabJournal Entry` j, `tabJournal Entry Account` a
|
||||
WHERE a.parent = j.name and a.reference_type='Loan' and a.reference_name = %s
|
||||
and account = %s
|
||||
''', (loan.name, loan.loan_account), as_dict=1)
|
||||
|
||||
for payment in payments:
|
||||
repayment_entry = make_repayment_entry(loan.name, loan.loan_applicant_type, loan.applicant,
|
||||
loan.loan_type, loan.company)
|
||||
|
||||
repayment_entry.amount_paid = payment.debit_in_account_currency
|
||||
repayment_entry.posting_date = payment.posting_date
|
||||
repayment_entry.save()
|
||||
repayment_entry.submit()
|
||||
|
||||
jv = frappe.get_doc('Journal Entry', payment.name)
|
||||
jv.flags.ignore_links = True
|
||||
jv.cancel()
|
||||
|
Loading…
x
Reference in New Issue
Block a user