def test_highest_interest_accruing(current_date): """ If there are multiple loans, it's the highest interest loans who are accruing that are addressed first. """ init_account_balance = Money(10000.00) account = Account(init_account_balance) init_loans = [] init_loan_balance = Money(100.00) bill_info = BillInfo( day=10, amount=Money(1.00)) # days after dates covered in this test accrue_start_date = current_date.date + datetime.timedelta(days=100) loan_info = LoanInfo(init_loan_balance, 1.00, accrue_start_date) init_loans.append(Loan(loan_info, bill_info)) loan_info = LoanInfo(init_loan_balance, 1.00) init_loans.append(Loan(loan_info, bill_info)) loans = copy.deepcopy(init_loans) payer = HighestInterestFirstPayer(loans, account, next_day(current_date.date), Money(50.00)) current_date.register(payer) current_date.increment_day() # first loan, nonaccruing, should not have a changed balance assert loans[0].balance == init_loans[0].balance # second loan should have a decreased balance assert loans[1].balance + Money(50.00) == init_loans[1].balance
def test_highest_interest_first(current_date): """ If there are 2+ loans, the loan with highest interest receives the payment. """ init_account_balance = Money(10000.00) account = Account(init_account_balance) init_loans = [] init_loan_balance = Money(100.00) bill_info = BillInfo( day=10, amount=Money(1.00)) # days after dates covered in this test loan_info = LoanInfo(init_loan_balance, interest=1.00) init_loans.append(Loan(loan_info, bill_info)) loan_info = LoanInfo(init_loan_balance, interest=loan_info.interest + 1.00) init_loans.append(Loan(loan_info, bill_info)) loans = copy.deepcopy(init_loans) payer = HighestInterestFirstPayer(loans, account, next_day(current_date.date), Money(100.00)) current_date.register(payer) current_date.increment_day() # second loan, the higher interest one, should have a different balance assert init_loans[1].balance != loans[1].balance # but lower interest one should be unchanged in this test assert init_loans[0].balance == loans[0].balance
def test_order_observers_regiester(): """ The order in which two observers are registered should not affect the update cycle. """ start = datetime.date(2020, 7, 4) date = DateSubject(start) end = date.date + datetime.timedelta(days=10) bill_info = BillInfo(day=end.day, amount=Money(10.00)) loan_info = LoanInfo(Money(1000.00), interest=1.00) loan = Loan(loan_info, bill_info) loan_copy = copy.deepcopy(loan) account = Account(Money(10000.00)) # a reserve of money date.register(MinPaymentPayer(loan, account)) date.register(InterestAccruer(loan)) date.register(InterestAccruer(loan_copy)) date.register(MinPaymentPayer(loan_copy, account)) for d in date_range(start, end): date.increment_day() # \todo These are off by a penny. Is that acceptable? assert almost_equal(loan.balance, loan_copy.balance, 0.01) assert almost_equal(loan.total_owed, loan_copy.total_owed, 0.01)
def test_dont_overpay_small_balance_loan(current_date): """ If a loan has only a small balance left, and the HighestInterestFirstPayer's amount is greater than that balance do not overpay. """ init_account_balance = Money(10000.00) account = Account(init_account_balance) init_loan_balance = Money(100.00) bill_info = BillInfo( day=10, amount=Money(1.00)) # days after dates covered in this test loan_info = LoanInfo(init_loan_balance, interest=1.00) loans = [Loan(loan_info, bill_info)] # pay day after current_date (5) pay_amount = Money(200.00) payer = HighestInterestFirstPayer(loans, account, next_day(current_date.date), pay_amount) init_total_owed = payer.total_owed current_date.register(payer) current_date.increment_day() assert account.balance + init_loan_balance == init_account_balance assert loans[0].total_owed == Money(0.00)
def test_account_loan_balance_adjusts(current_date): """ The total_owed on a loan and change in account balance should be changed in a specific way. """ init_account_balance = Money(10000.00) account = Account(init_account_balance) init_loan_balance = Money(100.00) bill_info = BillInfo( day=10, amount=Money(1.00)) # days after dates covered in this test loan_info = LoanInfo(init_loan_balance, interest=1.00) loans = [Loan(loan_info, bill_info)] # pay day after current_date (5) pay_amount = Money(10.00) payer = HighestInterestFirstPayer(loans, account, next_day(current_date.date), pay_amount) init_total_owed = payer.total_owed current_date.register(payer) current_date.increment_day() assert account.balance + pay_amount == init_account_balance assert loans[0].total_owed + pay_amount == init_loan_balance
def test_multiple_loans_highest_interest_first(current_date): """ If there are 2+ loans, where payer's amount covers at least one of the loan's remaining balance, and then some, the second highest interest loan is the loan whose balance gets paid down. """ init_account_balance = Money(10000.00) account = Account(init_account_balance) init_loans = [] init_loan_balance = Money(100.00) bill_info = BillInfo( day=10, amount=Money(1.00)) # days after dates covered in this test loan_info = LoanInfo(init_loan_balance, interest=1.00) init_loans.append(Loan(loan_info, bill_info)) loan_info = LoanInfo(init_loan_balance, interest=loan_info.interest + 1.00) init_loans.append(Loan(loan_info, bill_info)) loan_info = LoanInfo(init_loan_balance, interest=loan_info.interest - 0.50) init_loans.append(Loan(loan_info, bill_info)) loans = copy.deepcopy(init_loans) payer = HighestInterestFirstPayer(loans, account, next_day(current_date.date), init_loan_balance + Money(50.00)) current_date.register(payer) current_date.increment_day() # first loan in this test should remain unchanged. assert loans[0].balance == init_loans[0].balance # Second loan should have zero money left assert loans[1].balance == Money(0.00) # Third loan should have a reduced balance assert loans[2].balance == init_loans[2].balance - Money(50.00)
def test_nonzero_balance_loan(current_date): """ If there is a nonzero balance loan total owed of highinterestpayer should change, and account amount should change. """ init_account_balance = Money(10000.00) account = Account(init_account_balance) bill_info = BillInfo(day=10, amount=Money(1.00)) loan_info = LoanInfo(Money(100.00), interest=1.00) loans = [Loan(loan_info, bill_info)] payer = HighestInterestFirstPayer(loans, account, 8, Money(10.00)) init_total_owed = payer.total_owed current_date.register(payer) for i in range(31): current_date.increment_day() assert init_account_balance != account.balance assert init_total_owed != payer.total_owed
def create_loan(accrue_start_date=None): # create loan where minimum payment is the day after ptest fixture's date. bill_info = BillInfo(day=20, amount=Money(1.00)) loan_info = LoanInfo(Money(10000.00), interest=1.00, start_date=accrue_start_date) return Loan(loan_info, bill_info)
def zero_accured_loan(): """Return a loan with zero accrued interest with 1% interest rate (APR)""" bill_info = BillInfo(day=1, amount=Money()) loan_info = LoanInfo(Money(100.00), interest=1.00) return Loan(loan_info, bill_info)
def create_loan(initial_amount, min_payment, bill_start_date=None): # create loan where minimum payment is the day after ptest fixture's date. bill_info = BillInfo(day=5, amount=min_payment, start_date=bill_start_date) loan_info = LoanInfo(initial_amount, interest=1.00) return Loan(loan_info, bill_info)