Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
111 changes: 96 additions & 15 deletions abcbank/account.py
Original file line number Diff line number Diff line change
@@ -1,43 +1,124 @@
from abcbank.transaction import Transaction

import json, os
CHECKING = 0
SAVINGS = 1
MAXI_SAVINGS = 2

full_path = os.path.realpath(__file__)
config = os.path.dirname(full_path) + "/config.json"

class Account:
class Account(object):
def __init__(self, accountType):
self.accountType = accountType
self.configPath = ""
self.transactions = []

def deposit(self, amount):
#deposits an amount into a customer's account
if (amount <= 0):
raise ValueError("amount must be greater than zero")
else:
self.transactions.append(Transaction(amount))

def withdraw(self, amount):
#withdraws the amount specified from the customer's account
if (amount <= 0):
raise ValueError("amount must be greater than zero")
else:
self.transactions.append(Transaction(-amount))

def transfer(self, amount, toAcct):
#transfers the amount specified from one account to another.
#Once hooked into a database we can set a max for transfers based on account balances.
if (amount <= 0):
raise ValueError("amount must be greater than zero")
else:
self.transactions.append(Transaction(-amount))
toAcct.transactions.append(Transaction(amount))


def interestEarned(self):
def interestEarned(self, duration=None):
#interest eared over a duration, duration is expressed as 1 being one year,
#This version utilizes a json config file so that it can be quickly referenced
#by many files and easily edited without effecting the rest of the system or
#requiring a recommit.
json_data = open(config)
data = json.load(json_data)
json_data.close()
amount = self.sumTransactions()
#these allow for the use of duration and compound frequency without being required.
if duration is None:
duration = 1

if self.accountType == SAVINGS:
if (amount <= 1000):
return amount * 0.001
sb1=data["savings"][0]["breakpoint"]
sr1=data["savings"][0]["rate"]
sr2=data["savings"][1]["rate"]
sf =data["savings"][0]["frequency"]
freq = sf
if (amount <= sb1):
rate = sr1
earned = self.interestEarnedTime(amount,rate,freq,duration)
self.result = self.twoPlaces(earned)
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
rate = sr2
sofar = self.interestEarnedTime(sb1,sr1,freq,duration)
sb2 = self.interestEarnedTime((amount-sb1),rate,freq,duration)
earned = sofar + sb2
self.result = self.twoPlaces(earned)

elif self.accountType == MAXI_SAVINGS:
mb1=data["maxi"][0]["breakpoint"]
mr1=data["maxi"][0]["rate"]
mb2=data["maxi"][1]["breakpoint"]
mr2=data["maxi"][1]["rate"]
mr3=data["maxi"][2]["rate"]
mf =data["maxi"][0]["frequency"]
freq = mf
if (amount <= mb1):
rate = mr1
earned = self.interestEarnedTime(amount,rate,freq,duration)
self.result = self.twoPlaces(earned)

elif (amount <= mb2):
rate = mr2
principal = amount - mb1
earned =(mr1*mb1) + self.interestEarnedTime(principal,rate,freq,duration)
self.result = self.twoPlaces(earned)

else:
return 70 + (amount - 2000) * 0.1
else:
return amount * 0.001
rate = mr3
principal = amount - mb2
c1 = self.interestEarnedTime(mb1,mr1,freq,duration)
c2 = self.interestEarnedTime((mb2-mb1),mr2,freq,duration)
res = self.interestEarnedTime(principal,rate,freq,duration)
earned = c1 + c2 + res
self.result = self.twoPlaces(earned)

elif self.accountType == CHECKING:
cr1=data["checking"][0]["rate"]
cf =data["checking"][0]["frequency"]
freq = cf
rate = cr1
earned = self.interestEarnedTime(amount,rate,freq,duration)
self.result = self.twoPlaces(earned)

return self.result

def sumTransactions(self, checkAllTransactions=True):
return sum([t.amount for t in self.transactions])
return sum([t.amount for t in self.transactions])

def twoPlaces(self,value):
#quick reusable funciton to round to 2 spots to make it easier to put in to a dollar value
return float("{0:.2f}".format(value))

def interestEarnedTime(self,principal, rate,times_per_year, years):
#this function is the formula for interest and it can be set up to account
#for duration as well as compound frequency
# (1 + r/n)
body = 1 + (rate / times_per_year)
# nt
exponent = times_per_year * years
# P(1 + r/n)^nt
return principal * pow(body, exponent) -principal

8 changes: 8 additions & 0 deletions abcbank/bank.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,27 @@ def __init__(self):

def addCustomer(self, customer):
self.customers.append(customer)

def customerSummary(self):
#returns a summary of a customer's accounts
summary = "Customer Summary"
for customer in self.customers:
summary = summary + "\n - " + customer.name + " (" + self._format(customer.numAccs(), "account") + ")"
return summary

def _format(self, number, word):
#returns a formatted string with the proper sytax
return str(number) + " " + (word if (number == 1) else word + "s")

def totalInterestPaid(self):
#returns the total interest paid by the bank to all customers requested
total = 0
for c in self.customers:
total += c.totalInterestEarned()
return total

def getFirstCustomer(self):
#returns the first cutomer's name
try:
self.customers = None
return self.customers[0].name
Expand Down
4 changes: 4 additions & 0 deletions abcbank/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{"maxi":[{"rate":0.02,"breakpoint":1000.00,"frequency":365},{"rate":0.05,"breakpoint":2000.00},{"rate":0.1,"breakpoint":0}],
"savings":[{"rate":0.001,"breakpoint":1000.00,"frequency":365},{"rate":0.002}],
"checking":[{"frequency":365,"rate":0.001}]
}
22 changes: 13 additions & 9 deletions abcbank/customer.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from account import CHECKING, SAVINGS, MAXI_SAVINGS
from abcbank.account import CHECKING, SAVINGS, MAXI_SAVINGS


class Customer:
Expand All @@ -7,20 +7,20 @@ def __init__(self, name):
self.accounts = []

def openAccount(self, account):
#opens an account for customer
self.accounts.append(account)
return self

def numAccs(self):
#this returns the number of accounts
return len(self.accounts)

def totalInterestEarned(self):
#Returns the total interest earned across all acounts
return sum([a.interestEarned() for a in self.accounts])

# This method gets a statement

def getStatement(self):
# JIRA-123 Change by Joe Bloggs 29/7/1988 start
statement = None # reset statement to null here
# JIRA-123 Change by Joe Bloggs 29/7/1988 end
# This method gets a statement
totalAcrossAllAccounts = sum([a.sumTransactions() for a in self.accounts])
statement = "Statement for %s" % self.name
for account in self.accounts:
Expand All @@ -29,6 +29,7 @@ def getStatement(self):
return statement

def statementForAccount(self, account):
# This puts the statement in a human readable format.
accountType = "\n\n\n"
if account.accountType == CHECKING:
accountType = "\n\nChecking Account\n"
Expand All @@ -38,11 +39,13 @@ def statementForAccount(self, account):
accountType = "\n\nMaxi Savings Account\n"
transactionSummary = [self.withdrawalOrDepositText(t) + " " + _toDollars(abs(t.amount))
for t in account.transactions]
transactionSummary = " " + "\n ".join(transactionSummary) + "\n"
totalSummary = "Total " + _toDollars(sum([t.amount for t in account.transactions]))
return accountType + transactionSummary + totalSummary
joinedTransactionSummary = " " + "\n ".join(transactionSummary) + "\n"
self.balance = sum([t.amount for t in account.transactions])
totalSummary = "Total " + _toDollars(self.balance)
return accountType + joinedTransactionSummary + totalSummary

def withdrawalOrDepositText(self, transaction):
#returns proper text for if a transaction was a withdrawal or deposit
if transaction.amount < 0:
return "withdrawal"
elif transaction.amount > 0:
Expand All @@ -52,4 +55,5 @@ def withdrawalOrDepositText(self, transaction):


def _toDollars(number):
#returns float value to dollars.
return "${:1.2f}".format(number)
13 changes: 6 additions & 7 deletions tests/bank_tests.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
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():
Expand All @@ -25,14 +24,14 @@ def test_checking_account():
def test_savings_account():
bank = Bank()
checkingAccount = Account(SAVINGS)
bank.addCustomer(Customer("Bill").openAccount(checkingAccount))
bank.addCustomer(Customer("Andrew").openAccount(checkingAccount))
checkingAccount.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))
bank.addCustomer(Customer("Gabriela").openAccount(checkingAccount))
checkingAccount.deposit(3000.0)
assert_equals(bank.totalInterestPaid(), 170.0)
assert_equals(bank.totalInterestPaid(), 176.62)
46 changes: 33 additions & 13 deletions tests/customer_tests.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
from nose.tools import assert_equals, nottest

from account import Account, CHECKING, SAVINGS
from customer import Customer
from nose.tools import assert_equals
from abcbank.account import Account, CHECKING, SAVINGS, MAXI_SAVINGS
from abcbank.customer import Customer


def test_statement():
#statement test
checkingAccount = Account(CHECKING)
savingsAccount = Account(SAVINGS)
henry = Customer("Henry").openAccount(checkingAccount).openAccount(savingsAccount)
henry = Customer("Henry").openAccount(checkingAccount)
henry.openAccount(savingsAccount)
checkingAccount.deposit(100.0)
savingsAccount.deposit(4000.0)
savingsAccount.withdraw(200.0)
Expand All @@ -16,21 +17,40 @@ def test_statement():
"\n\nChecking Account\n deposit $100.00\nTotal $100.00" +
"\n\nSavings Account\n deposit $4000.00\n withdrawal $200.00\nTotal $3800.00" +
"\n\nTotal In All Accounts $3900.00")


def test_transfer():
#transfer test
checkingAccount = Account(CHECKING)
savingsAccount = Account(SAVINGS)
andy = Customer("Andy").openAccount(checkingAccount)
andy.openAccount(savingsAccount)
savingsAccount.deposit(4000.0)
savingsAccount.transfer(200.0,checkingAccount)
assert_equals(andy.getStatement(),
"Statement for Andy" +
"\n\nChecking Account\n deposit $200.00\nTotal $200.00" +
"\n\nSavings Account\n deposit $4000.00\n withdrawal $200.00\nTotal $3800.00" +
"\n\nTotal In All Accounts $4000.00")

def test_oneAccount():
#single account test
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)
#two account test
jerry = Customer("Jerry").openAccount(Account(SAVINGS))
jerry.openAccount(Account(CHECKING))
assert_equals(jerry.numAccs(), 2)


@nottest
def test_threeAccounts():
oscar = Customer("Oscar").openAccount(Account(SAVINGS))
oscar.openAccount(Account(CHECKING))
assert_equals(oscar.numAccs(), 3)
#two account test
steve = Customer("Steve").openAccount(Account(SAVINGS))
steve.openAccount(Account(CHECKING))
steve.openAccount(Account(MAXI_SAVINGS))
assert_equals(steve.numAccs(), 3)



3 changes: 1 addition & 2 deletions tests/transaction_tests.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from nose.tools import assert_is_instance

from transaction import Transaction
from abcbank.transaction import Transaction


def test_type():
Expand Down