diff --git a/erpnext/loan_management/doctype/loan/loan.js b/erpnext/loan_management/doctype/loan/loan.js index ffef60b6b0..6696386950 100644 --- a/erpnext/loan_management/doctype/loan/loan.js +++ b/erpnext/loan_management/doctype/loan/loan.js @@ -119,12 +119,10 @@ frappe.ui.form.on('Loan', { create_loan_security_unpledge: function(frm) { frappe.call({ - method: "erpnext.loan_management.doctype.loan.loan.create_loan_security_unpledge", + method: "erpnext.loan_management.doctype.loan.loan.unpledge_security", args : { "loan": frm.doc.name, - "applicant_type": frm.doc.applicant_type, - "applicant": frm.doc.applicant, - "company": frm.doc.company + "as_dict": 1 }, callback: function(r) { if (r.message) diff --git a/erpnext/loan_management/doctype/loan/loan.py b/erpnext/loan_management/doctype/loan/loan.py index e20b484fc0..e2e27dd45d 100644 --- a/erpnext/loan_management/doctype/loan/loan.py +++ b/erpnext/loan_management/doctype/loan/loan.py @@ -7,7 +7,7 @@ import frappe, math, json import erpnext from frappe import _ 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 class Loan(AccountsController): @@ -223,30 +223,52 @@ def make_repayment_entry(loan, applicant_type, applicant, loan_type, company, as return repayment_entry @frappe.whitelist() -def create_loan_security_unpledge(loan, applicant_type, applicant, company, as_dict=1): - loan_security_pledge_details = frappe.db.sql(""" - SELECT p.loan_security, sum(p.qty) as qty - FROM `tabLoan Security Pledge` lsp , `tabPledge` p - WHERE p.parent = lsp.name AND lsp.loan = %s AND lsp.docstatus = 1 - GROUP BY p.loan_security - """,(loan), as_dict=1) +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: + pledge_qty_map = get_pledged_security_qty(loan) + loan_doc = frappe.get_doc('Loan', loan) + unpledge_request = create_loan_security_unpledge(pledge_qty_map, loan_doc.name, loan_doc.company, + loan_doc.applicant_type, loan_doc.applicant) + # will unpledge qty based on loan security pledge + elif loan_security_pledge: + security_map = {} + pledge_doc = frappe.get_doc('Loan Security Pledge', loan_security_pledge) + for security in pledge_doc.securities: + security_map.setdefault(security.loan_security, security.qty) + unpledge_request = create_loan_security_unpledge(security_map, pledge_doc.loan, + pledge_doc.company, pledge_doc.applicant_type, pledge_doc.applicant) + + if approve: + unpledge_request.status = 'Approved' + + if save: + unpledge_request.save() + + if submit: + unpledge_request.submit() + + if as_dict: + return unpledge_request + else: + return unpledge_request + +def create_loan_security_unpledge(unpledge_map, loan, company, applicant_type, applicant): unpledge_request = frappe.new_doc("Loan Security Unpledge") unpledge_request.applicant_type = applicant_type unpledge_request.applicant = applicant unpledge_request.loan = loan unpledge_request.company = company - for loan_security in loan_security_pledge_details: - unpledge_request.append('securities', { - "loan_security": loan_security.loan_security, - "qty": loan_security.qty - }) + for security, qty in unpledge_map.items(): + if qty: + unpledge_request.append('securities', { + "loan_security": security, + "qty": qty + }) - if as_dict: - return unpledge_request.as_dict() - else: - return unpledge_request + return unpledge_request diff --git a/erpnext/loan_management/doctype/loan/test_loan.py b/erpnext/loan_management/doctype/loan/test_loan.py index 2f6cd25a36..5faf80e625 100644 --- a/erpnext/loan_management/doctype/loan/test_loan.py +++ b/erpnext/loan_management/doctype/loan/test_loan.py @@ -14,7 +14,7 @@ from erpnext.loan_management.doctype.process_loan_interest_accrual.process_loan_ 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 create_loan_security_unpledge +from erpnext.loan_management.doctype.loan.loan import unpledge_security 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 @@ -307,7 +307,7 @@ class TestLoan(unittest.TestCase): loan.load_from_db() self.assertEquals(loan.status, "Loan Closure Requested") - unpledge_request = create_loan_security_unpledge(loan.name, loan.applicant_type, loan.applicant, loan.company, as_dict=0) + unpledge_request = unpledge_security(loan=loan.name, save=1) unpledge_request.submit() unpledge_request.status = 'Approved' unpledge_request.save() 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 f6b28dae75..4cd3dad369 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 @@ -17,10 +17,12 @@ class LoanSecurityUnpledge(Document): self.validate_unpledge_qty() def on_cancel(self): - self.update_loan_security_pledge(cancel=1) self.update_loan_status(cancel=1) self.db_set('status', 'Requested') + def on_submit(self): + self.approve() + def validate_duplicate_securities(self): security_list = [] for d in self.securities: @@ -32,6 +34,7 @@ class LoanSecurityUnpledge(Document): def validate_unpledge_qty(self): pledge_qty_map = get_pledged_security_qty(self.loan) + print(pledge_qty_map, "$$$$$$$$") ltv_ratio_map = frappe._dict(frappe.get_all("Loan Security Type", fields=["name", "loan_to_value_ratio"], as_list=1)) @@ -50,8 +53,7 @@ class LoanSecurityUnpledge(Document): security_value = 0 for security in self.securities: - pledged_qty = pledge_qty_map.get(security.loan_security) - + pledged_qty = pledge_qty_map.get(security.loan_security, 0) if security.qty > pledged_qty: frappe.throw(_("""Row {0}: {1} {2} of {3} is pledged against Loan {4}. You are trying to unpledge more""").format(security.idx, pledged_qty, security.uom, @@ -60,16 +62,23 @@ class LoanSecurityUnpledge(Document): qty_after_unpledge = pledged_qty - security.qty ltv_ratio = ltv_ratio_map.get(security.loan_security_type) - security_value += qty_after_unpledge * loan_security_price_map.get(security.loan_security) + current_price = loan_security_price_map.get(security.loan_security) + if not current_price: + frappe.throw(_("No valid Loan Security Price found for {0}").format(frappe.bold(security.loan_security))) + + security_value += qty_after_unpledge * current_price if not security_value and flt(pending_principal_amount, 2) > 0: frappe.throw("Cannot Unpledge, loan to value ratio is breaching") - if security_value and (pending_principal_amount/security_value) * 100 > ltv_ratio: + if security_value and flt(pending_principal_amount/security_value) * 100 > ltv_ratio: frappe.throw("Cannot Unpledge, loan to value ratio is breaching") def on_update_after_submit(self): - if self.status == "Approved": + self.approve() + + def approve(self): + if self.status == "Approved" and not self.unpledge_time: self.update_loan_status() self.db_set('unpledge_time', get_datetime())