Exemple #1
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="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)
Exemple #2
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
Exemple #3
0
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
Exemple #4
0
    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)
Exemple #5
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)
Exemple #6
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)
Exemple #7
0
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)