def test_calculate_principal_and_duration_raises_error(self): ''' Test whether Loan Plan fields are missing ''' params = (20000.0, '_Test Loan Plan 2', '2020-08-19') with self.assertRaises(ValueError): calculate_principal_and_duration(*params)
def test_calculate_principal_and_duration_raises_when_invalid_plan(self): ''' Test for invalid Loan Plan dict ''' params = (20000.0, 104, '2020-08-19') with self.assertRaises(ValueError): calculate_principal_and_duration(*params)
def validate(self): effective_date = frappe.get_value('Loan Plan', self.loan_plan, 'date_effective_from') if effective_date and \ getdate(effective_date) > getdate(self.posting_date): return None if self.stipulated_recovery_amount > self.loan_principal: frappe.throw("Recovery Amount cannot exceed Principal.") date_of_retirement, net_salary_amount = frappe.get_value( 'Loanee Details', {'customer': self.customer}, ['date_of_retirement', 'net_salary_amount']) force_duration, income_multiple, max_duration = frappe.get_value( 'Loan Plan', self.loan_plan, ['force_duration', 'income_multiple', 'max_duration']) check = calculate_principal_and_duration( income=net_salary_amount, loan_plan={ 'force_duration': force_duration, 'income_multiple': income_multiple, 'max_duration': max_duration, 'billing_day': getdate(self.billing_date).day, 'rate_of_interest': self.rate_of_interest, }, end_date=date_of_retirement, execution_date=self.posting_date) if self.loan_principal > flt(check.get('principal')): frappe.throw("Requested principal cannot exceed {}.".format( self.fmt_money(check.get('principal')))) if self.stipulated_recovery_amount < \ self.loan_principal / check.get('duration'): frappe.throw("Recovery Amount can be less than {}.".format( self.fmt_money(self.loan_principal / check.get('duration')))) # possible heavy db queries ahead so check for outstanding is # positioned last outstanding_principal = reduce( (lambda a, x: a + get_outstanding_principal( x.name, self.posting_date)), frappe.get_all('Loan', filters={ 'customer': self.customer, 'docstatus': 1, 'recovery_status': ('in', 'Not Started, In Progress'), }), 0) if self.loan_principal + outstanding_principal > \ flt(check.get('principal')): frappe.throw(""" Customer has existing loans of outstanding {}. Total principal should not exceed allowable principal {}. """.format(self.fmt_money(outstanding_principal), self.fmt_money(check.get('principal')))) self.expected_end_date = check.get('expected_eta')
def test_calculate_principal_and_duration(self): '''Test calculate_principal_and_duration default case''' actual = calculate_principal_and_duration( 20000.0, '_Test Loan Plan 1', '2030-08-19', '2017-12-12', ) expected = { 'principal': 480000.0, 'expected_eta': '2023-01-04', 'duration': 60, 'recovery_amount': 8000.0, 'initial_interest': 24000.0, } self.assertEqual(actual, expected)
def test_calculate_principal_force_duration(self): ''' Test calculate_principal_and_duration when the end_date is ignored in Loan Plan. ''' actual = calculate_principal_and_duration( 20000.0, '_Test Loan Plan 3', '2020-08-19', '2017-12-12', ) expected = { 'principal': 480000.0, 'expected_eta': '2023-01-04', 'duration': 60, 'recovery_amount': 8000.0, 'initial_interest': 24000.0, } self.assertEqual(actual, expected)
def test_calculate_principal_and_duration_end_date_before_loan_plan_max_duration( self): ''' Test calculate_principal_and_duration when the end_date is before Loan Plan.max duration. ''' actual = calculate_principal_and_duration( 20000.0, '_Test Loan Plan 1', '2020-08-19', '2017-12-12', ) expected = { 'principal': 248000.0, 'expected_eta': '2020-08-04', 'duration': 31, 'recovery_amount': 8000.0, 'initial_interest': 12500.0, } self.assertEqual(actual, expected)
def test_calculate_principal_and_duration_when_plan_is_dict(self): '''Test when loan_plan param is a dict''' actual = calculate_principal_and_duration( 20000.0, { 'income_multiple': 24, 'max_duration': 60, 'billing_day': 5, 'rate_of_interest': 5.0, }, '2020-08-19', '2017-12-12', ) expected = { 'principal': 248000.0, 'expected_eta': '2020-08-04', 'duration': 31, 'recovery_amount': 8000.0, 'initial_interest': 12400.0, } self.assertEqual(actual, expected)