diff --git a/abcbank/account.py b/abcbank/account.py index e010009..38528ab 100644 --- a/abcbank/account.py +++ b/abcbank/account.py @@ -1,43 +1,90 @@ from abcbank.transaction import Transaction +import datetime as D CHECKING = 0 SAVINGS = 1 MAXI_SAVINGS = 2 +DEP_WITH = 0 +TRANSFER = 1 + +""" +1) transfer between their accounts +2) Change Maxi-Savings accounts to have an interest rate of 5% assuming + no withdrawals in the past 10 days otherwise 0.1% +3) Interest rates should accrue daily (incl. wknds), rates above are per-annum""" + + +def compound_interest(principal, rate, times_per_year, years): + body = 1 + (rate / times_per_year) # (1 + r/n) + exponent = times_per_year * years # P(1 + r/n)^nt + intEarned = (principal * pow(body, exponent)) - principal + return intEarned class Account: def __init__(self, accountType): self.accountType = accountType self.transactions = [] - def deposit(self, amount): - if (amount <= 0): - raise ValueError("amount must be greater than zero") - else: - self.transactions.append(Transaction(amount)) + def deposit(self, amount, tDte=D.date.today()): + if (amount <= 0): raise ValueError("amount must be greater than zero") + else: self.transactions.append(Transaction(amount, tDte, DEP_WITH)) + + def withdraw(self, amount, tDte=D.date.today()): + if (amount <= 0): raise ValueError("amount must be greater than zero") + else: self.transactions.append(Transaction(-amount, tDte, DEP_WITH)) - def withdraw(self, amount): - if (amount <= 0): - raise ValueError("amount must be greater than zero") - else: - self.transactions.append(Transaction(-amount)) + def transfer(self, toAcct, amount, tDte=D.date.today()): + if (amount <= 0): raise ValueError("amount must be greater than zero") + else: + self.transactions.append(Transaction(-amount, tDte, TRANSFER)) + toAcct.transactions.append(Transaction(+amount, tDte, TRANSFER)) def interestEarned(self): amount = self.sumTransactions() if self.accountType == SAVINGS: - if (amount <= 1000): - return amount * 0.001 - else: - return 1 + (amount - 1000) * 0.002 - if self.accountType == MAXI_SAVINGS: - if (amount <= 1000): - return amount * 0.02 - elif (amount <= 2000): - return 20 + (amount - 1000) * 0.05 - else: - return 70 + (amount - 2000) * 0.1 - else: - return amount * 0.001 + if (amount <= 1000): return amount * 0.001 + else: return 1 + (amount - 1000) * 0.002 + elif self.accountType == MAXI_SAVINGS: + if (self.withdrawnInLast10()): return amount * 0.001 + else: return amount * 0.05 + + if (amount <= 1000): return amount * 0.02 + elif (amount <= 2000): return 20 + (amount - 1000) * 0.05 + else: return 70 + (amount - 2000) * 0.1 + elif self.accountType == CHECKING: return amount * 0.001 + else: raise ValueError("Unknown Acct Type") + + def N_interestEarned(self): + if len(self.transactions) == 0: return 0 + sum_intEarned = 0 + sum_amt = self.transactions[0].amount + last_transaction_date = self.transactions[0].transactionDate + last_withdrawl_date = D.date(1970,1,1) + for t in self.transactions[1:]: + nDays = (t.transactionDate-last_transaction_date).days + sum_amt += t.amount + lowr_maxi = (t.transactionDate - last_withdrawl_date).days <= 10 + annual_rate = self.calc_interestRate(sum_amt, lowr_maxi) + sum_intEarned += compound_interest(sum_amt, annual_rate, 365, nDays/365) + if t.amount < 0: last_withdrawl_date = t.transactionDate + return sum_intEarned + + def calc_interestRate(self, amount, low_maxi): + if self.accountType == SAVINGS: + if (amount <= 1000): return 0.001 + else: return (1 + (amount - 1000) * 0.002) / amount + elif self.accountType == MAXI_SAVINGS: + if (low_maxi): return 0.001 + else: return 0.05 + elif self.accountType == CHECKING: return 0.001 + else: raise ValueError("Unknown Acct Type") def sumTransactions(self, checkAllTransactions=True): - return sum([t.amount for t in self.transactions]) \ No newline at end of file + return sum([t.amount for t in self.transactions]) + + def withdrawnInLast10(self): + today = D.date.today() + for t in self.transactions: + if (((today-t.transactionDate).days <= 10) and (t.amount < 0) ): return 1 + return 0 diff --git a/abcbank/bank.py b/abcbank/bank.py index 44711fe..869f745 100644 --- a/abcbank/bank.py +++ b/abcbank/bank.py @@ -16,10 +16,17 @@ def totalInterestPaid(self): for c in self.customers: total += c.totalInterestEarned() return total + + def N_totalInterestPaid(self): + total = 0 + for c in self.customers: + total += c.N_totalInterestEarned() + return total + def getFirstCustomer(self): try: self.customers = None return self.customers[0].name except Exception as e: print(e) - return "Error" \ No newline at end of file + return "Error" diff --git a/abcbank/customer.py b/abcbank/customer.py index 7cfd62a..de3e8af 100644 --- a/abcbank/customer.py +++ b/abcbank/customer.py @@ -1,5 +1,6 @@ -from account import CHECKING, SAVINGS, MAXI_SAVINGS +import os, sys +from abcbank.account import CHECKING, SAVINGS, MAXI_SAVINGS class Customer: def __init__(self, name): @@ -16,6 +17,9 @@ def numAccs(self): def totalInterestEarned(self): return sum([a.interestEarned() for a in self.accounts]) + def N_totalInterestEarned(self): + return sum([a.N_interestEarned() for a in self.accounts]) + # This method gets a statement def getStatement(self): # JIRA-123 Change by Joe Bloggs 29/7/1988 start @@ -30,12 +34,9 @@ def getStatement(self): def statementForAccount(self, account): accountType = "\n\n\n" - if account.accountType == CHECKING: - accountType = "\n\nChecking Account\n" - if account.accountType == SAVINGS: - accountType = "\n\nSavings Account\n" - if account.accountType == MAXI_SAVINGS: - accountType = "\n\nMaxi Savings Account\n" + if account.accountType == CHECKING: accountType = "\n\nChecking Account\n" + if account.accountType == SAVINGS: accountType = "\n\nSavings Account\n" + if account.accountType == MAXI_SAVINGS: accountType = "\n\nMaxi Savings Account\n" transactionSummary = [self.withdrawalOrDepositText(t) + " " + _toDollars(abs(t.amount)) for t in account.transactions] transactionSummary = " " + "\n ".join(transactionSummary) + "\n" @@ -43,12 +44,13 @@ def statementForAccount(self, account): return accountType + transactionSummary + totalSummary def withdrawalOrDepositText(self, transaction): - if transaction.amount < 0: - return "withdrawal" - elif transaction.amount > 0: - return "deposit" - else: - return "N/A" + if transaction.tType == 1: + retStr = "Transfer " + print('#####in here') + else: retStr = "" + if transaction.amount < 0: return retStr+"withdrawal" + elif transaction.amount > 0: return retStr+"deposit" + else: return "N/A" def _toDollars(number): diff --git a/abcbank/date_provider.py b/abcbank/date_provider.py index 33b64eb..1a153a8 100644 --- a/abcbank/date_provider.py +++ b/abcbank/date_provider.py @@ -1,7 +1,6 @@ from datetime import datetime - class DateProvider: @staticmethod def now(): - return datetime.now() \ No newline at end of file + return datetime.now() diff --git a/abcbank/transaction.py b/abcbank/transaction.py index 8e5b5ad..0a94f6f 100644 --- a/abcbank/transaction.py +++ b/abcbank/transaction.py @@ -1,7 +1,7 @@ -from datetime import datetime - +import datetime as D class Transaction: - def __init__(self, amount): + def __init__(self, amount, tDate=D.date.today(), tType=0): self.amount = amount - self.transactionDate = datetime.now() \ No newline at end of file + self.transactionDate = tDate + self.tType = tType diff --git a/tests/bank_tests.py b/tests/bank_tests.py index 6de98db..e79963d 100644 --- a/tests/bank_tests.py +++ b/tests/bank_tests.py @@ -1,8 +1,11 @@ +import os, sys +import datetime as D + from nose.tools import assert_equals -from account import Account, CHECKING, MAXI_SAVINGS, SAVINGS -from bank import Bank -from customer import Customer +from abcbank.account import Account, CHECKING, MAXI_SAVINGS, SAVINGS +from abcbank.bank import Bank +from abcbank.customer import Customer def test_customer_summary(): @@ -24,15 +27,45 @@ def test_checking_account(): def test_savings_account(): bank = Bank() - checkingAccount = Account(SAVINGS) - bank.addCustomer(Customer("Bill").openAccount(checkingAccount)) - checkingAccount.deposit(1500.0) + savingsAccount = Account(SAVINGS) + bank.addCustomer(Customer("Bill").openAccount(savingsAccount)) + savingsAccount.deposit(1500.0) assert_equals(bank.totalInterestPaid(), 2.0) def test_maxi_savings_account(): bank = Bank() - checkingAccount = Account(MAXI_SAVINGS) - bank.addCustomer(Customer("Bill").openAccount(checkingAccount)) - checkingAccount.deposit(3000.0) - assert_equals(bank.totalInterestPaid(), 170.0) \ No newline at end of file + maxiAccount = Account(MAXI_SAVINGS) + bank.addCustomer(Customer("Bill").openAccount(maxiAccount)) + maxiAccount.deposit(3000.0) + print(bank.totalInterestPaid()) + assert_equals(bank.totalInterestPaid(), 150.0) + +def test_MaxiAcct_last10(): + bank = Bank() + maxiAccount = Account(MAXI_SAVINGS) + savingsAccount = Account(SAVINGS) + bank.addCustomer(Customer("Magnus").openAccount(maxiAccount).openAccount(savingsAccount)) + maxiAccount.deposit(100.0, D.date(2016,1,10)) + maxiAccount.deposit(100.0, D.date(2016,1,10)) + maxiAccount.withdraw(10.0, D.date(2016,8,20)) + print(bank.totalInterestPaid()) + assert_equals(bank.totalInterestPaid(), .19) + +def test_N_interestDaily(): + bank = Bank() + maxiAccount = Account(MAXI_SAVINGS) + savingsAccount = Account(SAVINGS) + bank.addCustomer(Customer("Magnus").openAccount(maxiAccount).openAccount(savingsAccount)) + maxiAccount.deposit(100.0, D.date(2016,1,10)) + maxiAccount.deposit(100.0, D.date(2016,2,10)) + maxiAccount.withdraw(10.0, D.date(2016,8,20)) + print(bank.N_totalInterestPaid()) + +if 1: # __name__ == '__main__': + test_customer_summary() + test_checking_account() + test_savings_account() + test_maxi_savings_account() + test_MaxiAcct_last10() + test_N_interestDaily() diff --git a/tests/customer_tests.py b/tests/customer_tests.py index 0211a4f..c2f939e 100644 --- a/tests/customer_tests.py +++ b/tests/customer_tests.py @@ -1,7 +1,10 @@ +import os, sys +import datetime as D + from nose.tools import assert_equals, nottest -from account import Account, CHECKING, SAVINGS -from customer import Customer +from abcbank.account import Account, CHECKING, SAVINGS +from abcbank.customer import Customer def test_statement(): @@ -17,20 +20,32 @@ def test_statement(): "\n\nSavings Account\n deposit $4000.00\n withdrawal $200.00\nTotal $3800.00" + "\n\nTotal In All Accounts $3900.00") - def test_oneAccount(): oscar = Customer("Oscar").openAccount(Account(SAVINGS)) assert_equals(oscar.numAccs(), 1) - def test_twoAccounts(): oscar = Customer("Oscar").openAccount(Account(SAVINGS)) oscar.openAccount(Account(CHECKING)) assert_equals(oscar.numAccs(), 2) - @nottest def test_threeAccounts(): oscar = Customer("Oscar").openAccount(Account(SAVINGS)) oscar.openAccount(Account(CHECKING)) - assert_equals(oscar.numAccs(), 3) \ No newline at end of file + assert_equals(oscar.numAccs(), 3) + +def test_Transf_Statement(): + checkingAccount = Account(CHECKING) + savingsAccount = Account(SAVINGS) + henry = Customer("Henry").openAccount(checkingAccount).openAccount(savingsAccount) + checkingAccount.deposit(100.0) + savingsAccount.deposit(4000.0) + savingsAccount.withdraw(200.0) + savingsAccount.transfer(checkingAccount, 50) + print(henry.getStatement()) + +test_oneAccount() +test_twoAccounts() +test_statement() +test_Transf_Statement() diff --git a/tests/transaction_tests.py b/tests/transaction_tests.py index 62caa8a..e02933c 100644 --- a/tests/transaction_tests.py +++ b/tests/transaction_tests.py @@ -1,8 +1,11 @@ -from nose.tools import assert_is_instance +import os, sys -from transaction import Transaction +from nose.tools import assert_is_instance +from abcbank.transaction import Transaction def test_type(): t = Transaction(5) - assert_is_instance(t, Transaction, "correct type") \ No newline at end of file + assert_is_instance(t, Transaction, "correct type") + +test_type()