def test_loan_amount_write_off(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.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 += 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) # repay 100 less so that it can be automatically written off repayment_entry = create_repayment_entry( loan.name, self.applicant2, add_days(last_date, 5), flt(loan.loan_amount + accrued_interest_amount - 100)) repayment_entry.submit() amount = frappe.db.get_value('Loan Interest Accrual', {'loan': loan.name}, ['sum(paid_interest_amount)']) self.assertEquals(flt(amount, 0), flt(accrued_interest_amount, 0)) self.assertEquals(flt(repayment_entry.penalty_amount, 5), 0) amounts = calculate_amounts(loan.name, add_days(last_date, 5)) self.assertEquals(flt(amounts['pending_principal_amount'], 0), 100) we = make_loan_write_off(loan.name, amount=amounts['pending_principal_amount']) we.submit() amounts = calculate_amounts(loan.name, add_days(last_date, 5)) self.assertEquals(flt(amounts['pending_principal_amount'], 0), 0)
def test_pending_loan_amount_after_closure_request(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.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 += 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) amounts = calculate_amounts(loan.name, add_days(last_date, 5)) repayment_entry = create_repayment_entry( loan.name, self.applicant2, add_days(last_date, 5), 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']) request_loan_closure(loan.name) loan.load_from_db() self.assertEquals(loan.status, "Loan Closure Requested") amounts = calculate_amounts(loan.name, add_days(last_date, 5)) self.assertTrue(amounts['pending_principal_amount'] < 0.0)
def test_loan_topup_with_additional_pledge(self): pledge = [{"loan_security": "Test Security 1", "qty": 4000.00}] loan_application = create_loan_application('_Test Company', self.applicant, 'Demand Loan', pledge) create_pledge(loan_application) loan = create_demand_loan(self.applicant, "Demand Loan", loan_application, posting_date='2019-10-01') loan.submit() self.assertEquals(loan.loan_amount, 1000000) first_date = '2019-10-01' last_date = '2019-10-30' # Disbursed 10,00,000 amount make_loan_disbursement_entry(loan.name, loan.loan_amount, disbursement_date=first_date) process_loan_interest_accrual_for_demand_loans(posting_date=last_date) amounts = calculate_amounts(loan.name, add_days(last_date, 1)) previous_interest = amounts['interest_amount'] pledge1 = [{"loan_security": "Test Security 1", "qty": 2000.00}] create_loan_security_pledge(self.applicant, pledge1, loan=loan.name) # Topup 500000 make_loan_disbursement_entry(loan.name, 500000, disbursement_date=add_days(last_date, 1)) process_loan_interest_accrual_for_demand_loans( posting_date=add_days(last_date, 15)) amounts = calculate_amounts(loan.name, add_days(last_date, 15)) per_day_interest = get_per_day_interest(1500000, 13.5, '2019-10-30') interest = per_day_interest * 15 self.assertEquals(amounts['pending_principal_amount'], 1500000) self.assertEquals(amounts['interest_amount'], flt(interest + previous_interest, 2))
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.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 += 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.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, 5)) self.assertTrue(amounts['pending_principal_amount'] < 0) self.assertEquals(amounts['payable_principal_amount'], 0.0) self.assertEqual(amounts['interest_amount'], 0)
def calculate_accrual_amount_for_demand_loans(loan, posting_date, process_loan_interest, accrual_type): from erpbee.loan_management.doctype.loan_repayment.loan_repayment import calculate_amounts no_of_days = get_no_of_days_for_interest_accural(loan, posting_date) precision = cint(frappe.db.get_default("currency_precision")) or 2 if no_of_days <= 0: return if loan.status == 'Disbursed': pending_principal_amount = flt(loan.total_payment) - flt(loan.total_interest_payable) \ - flt(loan.total_principal_paid) - flt(loan.written_off_amount) else: pending_principal_amount = flt(loan.disbursed_amount) - flt(loan.total_interest_payable) \ - flt(loan.total_principal_paid) - flt(loan.written_off_amount) interest_per_day = get_per_day_interest(pending_principal_amount, loan.rate_of_interest, posting_date) payable_interest = interest_per_day * no_of_days args = frappe._dict({ 'loan': loan.name, 'applicant_type': loan.applicant_type, 'applicant': loan.applicant, 'interest_income_account': loan.interest_income_account, 'loan_account': loan.loan_account, 'pending_principal_amount': pending_principal_amount, 'interest_amount': payable_interest, 'penalty_amount': calculate_amounts(loan.name, posting_date)['penalty_amount'], 'process_loan_interest': process_loan_interest, 'posting_date': posting_date, 'accrual_type': accrual_type }) if flt(payable_interest, precision) > 0.0: make_loan_interest_accrual_entry(args)
def test_penalty(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.assertEquals(loan.loan_amount, 1000000) first_date = '2019-10-01' last_date = '2019-10-30' make_loan_disbursement_entry(loan.name, loan.loan_amount, disbursement_date=first_date) process_loan_interest_accrual_for_demand_loans(posting_date=last_date) amounts = calculate_amounts(loan.name, add_days(last_date, 1)) paid_amount = amounts['interest_amount'] / 2 repayment_entry = create_repayment_entry(loan.name, self.applicant2, add_days(last_date, 5), paid_amount) repayment_entry.submit() # 30 days - grace period penalty_days = 30 - 4 penalty_applicable_amount = flt(amounts['interest_amount'] / 2, 2) penalty_amount = flt( (((penalty_applicable_amount * 25) / 100) * penalty_days), 2) process = process_loan_interest_accrual_for_demand_loans( posting_date='2019-11-30') calculated_penalty_amount = frappe.db.get_value( 'Loan Interest Accrual', { 'process_loan_interest_accrual': process, 'loan': loan.name }, 'penalty_amount') self.assertEquals(calculated_penalty_amount, penalty_amount)
def test_partial_unaccrued_interest_payment(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.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 += 5.5 # get partial unaccrued interest amount paid_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) amounts = calculate_amounts(loan.name, add_days(last_date, 5)) repayment_entry = create_repayment_entry(loan.name, self.applicant2, add_days(last_date, 5), paid_amount) repayment_entry.submit() repayment_entry.load_from_db() partial_accrued_interest_amount = (loan.loan_amount * loan.rate_of_interest * 5) \ / (days_in_year(get_datetime(first_date).year) * 100) interest_amount = flt( amounts['interest_amount'] + partial_accrued_interest_amount, 2) self.assertEqual(flt(repayment_entry.total_interest_paid, 0), flt(interest_amount, 0))
def request_loan_closure(loan, posting_date=None): if not posting_date: posting_date = getdate() amounts = calculate_amounts(loan, posting_date) pending_amount = amounts['payable_amount'] + amounts['unaccrued_interest'] 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 pending_amount < write_off_limit: # update status as loan closure requested frappe.db.set_value('Loan', loan, 'status', 'Loan Closure Requested') else: frappe.throw( _("Cannot close loan as there is an outstanding of {0}").format( pending_amount))
def make_loan_write_off(loan, company=None, posting_date=None, amount=0, as_dict=0): if not company: company = frappe.get_value('Loan', loan, 'company') if not posting_date: posting_date = getdate() amounts = calculate_amounts(loan, posting_date) pending_amount = amounts['pending_principal_amount'] if amount and (amount > pending_amount): frappe.throw( 'Write Off amount cannot be greater than pending loan amount') if not amount: amount = pending_amount # get default write off account from company master write_off_account = frappe.get_value('Company', company, 'write_off_account') write_off = frappe.new_doc('Loan Write Off') write_off.loan = loan write_off.posting_date = posting_date write_off.write_off_account = write_off_account write_off.write_off_amount = amount write_off.save() if as_dict: return write_off.as_dict() else: return write_off