def test_loan_security_unpledge(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.assertEqual(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 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) repayment_entry = create_repayment_entry( loan.name, self.applicant2, add_days(last_date, 5), flt(loan.loan_amount + accrued_interest_amount), ) repayment_entry.submit() request_loan_closure(loan.name) loan.load_from_db() self.assertEqual(loan.status, "Loan Closure Requested") unpledge_request = unpledge_security(loan=loan.name, save=1) unpledge_request.submit() unpledge_request.status = "Approved" unpledge_request.save() loan.load_from_db() pledged_qty = get_pledged_security_qty(loan.name) self.assertEqual(loan.status, "Closed") self.assertEqual(sum(pledged_qty.values()), 0) amounts = amounts = calculate_amounts(loan.name, add_days(last_date, 5)) self.assertEqual(amounts["pending_principal_amount"], 0) self.assertEqual(amounts["payable_principal_amount"], 0.0) self.assertEqual(amounts["interest_amount"], 0)
def get_total_pledged_security_value(loan): update_time = get_datetime() loan_security_price_map = frappe._dict( frappe.get_all( "Loan Security Price", fields=["loan_security", "loan_security_price"], filters={ "valid_from": ("<=", update_time), "valid_upto": (">=", update_time) }, as_list=1, )) hair_cut_map = frappe._dict( frappe.get_all("Loan Security", fields=["name", "haircut"], as_list=1)) security_value = 0.0 pledged_securities = get_pledged_security_qty(loan) for security, qty in pledged_securities.items(): after_haircut_percentage = 100 - hair_cut_map.get(security) security_value += (loan_security_price_map.get(security) * qty * after_haircut_percentage) / 100 return security_value
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 save: unpledge_request.save() if submit: unpledge_request.submit() if approve: if unpledge_request.docstatus == 1: unpledge_request.status = 'Approved' unpledge_request.save() else: frappe.throw(_('Only submittted unpledge requests can be approved')) if as_dict: return unpledge_request else: return unpledge_request
def test_loan_security_unpledge(self): pledges = [] pledges.append({ "loan_security": "Test Security 1", "qty": 4000.00, "haircut": 50 }) loan_security_pledge = create_loan_security_pledge( self.applicant2, pledges) loan = create_demand_loan(self.applicant2, "Demand Loan", loan_security_pledge.name, posting_date=get_first_day(nowdate())) 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) 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.submit() amounts = frappe.db.get_value( 'Loan Interest Accrual', {'loan': loan.name}, ['paid_interest_amount', 'paid_principal_amount']) 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.submit() unpledge_request.status = 'Approved' unpledge_request.save() loan.load_from_db() pledged_qty = get_pledged_security_qty(loan.name) self.assertEqual(loan.status, 'Closed') self.assertEquals(sum(pledged_qty.values()), 0)
def test_loan_security_unpledge(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=get_first_day(nowdate())) 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) 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.submit() loan.load_from_db() self.assertEquals(loan.status, "Loan Closure Requested") unpledge_request = unpledge_security(loan=loan.name, save=1) unpledge_request.submit() unpledge_request.status = 'Approved' unpledge_request.save() loan.load_from_db() pledged_qty = get_pledged_security_qty(loan.name) 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) self.assertEqual(amounts['interest_amount'], 0)
def check_for_ltv_shortfall(process_loan_security_shortfall): update_time = get_datetime() loan_security_price_map = frappe._dict( frappe.get_all("Loan Security Price", fields=["loan_security", "loan_security_price"], filters={ "valid_from": ("<=", update_time), "valid_upto": (">=", update_time) }, as_list=1)) loans = frappe.get_all('Loan', fields=[ 'name', 'loan_amount', 'total_principal_paid', 'total_payment', 'total_interest_payable', 'disbursed_amount', 'status' ], filters={ 'status': ('in', ['Disbursed', 'Partially Disbursed']), 'is_secured_loan': 1 }) loan_security_map = {} for loan in loans: if loan.status == 'Disbursed': outstanding_amount = flt(loan.total_payment) - flt(loan.total_interest_payable) \ - flt(loan.total_principal_paid) else: outstanding_amount = loan.disbursed_amount pledged_securities = get_pledged_security_qty(loan.name) ltv_ratio = '' security_value = 0.0 for security, qty in pledged_securities.items(): if not ltv_ratio: ltv_ratio = get_ltv_ratio(security) security_value += loan_security_price_map.get(security) * qty current_ratio = (outstanding_amount / security_value) * 100 if current_ratio > ltv_ratio: shortfall_amount = outstanding_amount - ( (security_value * ltv_ratio) / 100) create_loan_security_shortfall(loan.name, outstanding_amount, security_value, shortfall_amount, process_loan_security_shortfall)
def unpledge_security(loan=None, loan_security_pledge=None, security_map=None, as_dict=0, save=0, submit=0, approve=0): # if no security_map is passed it will be considered as full unpledge if security_map and isinstance(security_map, string_types): security_map = json.loads(security_map) if loan: pledge_qty_map = security_map or 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 save: unpledge_request.save() if submit: unpledge_request.submit() if approve: if unpledge_request.docstatus == 1: unpledge_request.status = "Approved" unpledge_request.save() else: frappe.throw( _("Only submittted unpledge requests can be approved")) if as_dict: return unpledge_request else: return unpledge_request
def check_for_ltv_shortfall(process_loan_security_shortfall): update_time = get_datetime() loan_security_price_map = frappe._dict( frappe.get_all( "Loan Security Price", fields=["loan_security", "loan_security_price"], filters={ "valid_from": ("<=", update_time), "valid_upto": (">=", update_time) }, as_list=1, )) loans = frappe.get_all( "Loan", fields=[ "name", "loan_amount", "total_principal_paid", "total_payment", "total_interest_payable", "disbursed_amount", "status", ], filters={ "status": ("in", ["Disbursed", "Partially Disbursed"]), "is_secured_loan": 1 }, ) loan_shortfall_map = frappe._dict( frappe.get_all("Loan Security Shortfall", fields=["loan", "name"], filters={"status": "Pending"}, as_list=1)) loan_security_map = {} for loan in loans: if loan.status == "Disbursed": outstanding_amount = (flt(loan.total_payment) - flt(loan.total_interest_payable) - flt(loan.total_principal_paid)) else: outstanding_amount = (flt(loan.disbursed_amount) - flt(loan.total_interest_payable) - flt(loan.total_principal_paid)) pledged_securities = get_pledged_security_qty(loan.name) ltv_ratio = 0.0 security_value = 0.0 for security, qty in pledged_securities.items(): if not ltv_ratio: ltv_ratio = get_ltv_ratio(security) security_value += flt( loan_security_price_map.get(security)) * flt(qty) current_ratio = (outstanding_amount / security_value) * 100 if security_value else 0 if current_ratio > ltv_ratio: shortfall_amount = outstanding_amount - ( (security_value * ltv_ratio) / 100) create_loan_security_shortfall( loan.name, outstanding_amount, security_value, shortfall_amount, current_ratio, process_loan_security_shortfall, ) elif loan_shortfall_map.get(loan.name): shortfall_amount = outstanding_amount - ( (security_value * ltv_ratio) / 100) if shortfall_amount <= 0: shortfall = loan_shortfall_map.get(loan.name) update_pending_shortfall(shortfall)