Skip to content

Completed Bank Accounts #64

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 20 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
b79bdfe
Add wave 3
kariabancroft Oct 8, 2015
84e2637
Merge remote-tracking branch 'upstream/master' into darg/master
daphnegold Oct 8, 2015
0ac02bc
Added bank.rb and savings-account.rb with SavingsAccount class
daphnegold Oct 8, 2015
8651592
Added withdraw functionality to SavingsAccount class
daphnegold Oct 8, 2015
6ec9927
New add_interest(rate) method added to SavingsAccount
daphnegold Oct 8, 2015
9b8e9ce
More withdraw functionality for CheckingAccount
daphnegold Oct 8, 2015
af90b60
Withdraw_using_check now keeps track of checks/fees, reset_checks
daphnegold Oct 8, 2015
823e667
Added MoneyMarketAccount class with max 6 deposit/withdraw
daphnegold Oct 8, 2015
bc3fd3f
MoneyMarketAccount lock for balance < 1000000
daphnegold Oct 8, 2015
3c881c9
Improved Deposit functionality for MoneyMarketAccount
daphnegold Oct 8, 2015
6ea2ce6
add_interest(rate), reset_transactions methods for MoneyMarketAcc
daphnegold Oct 8, 2015
947cf13
Deposit/Withdraw methods for all classes no longer take neg input
daphnegold Oct 9, 2015
ffae6d8
master_list now in Bank::Owner. Owner can 'have-many' accounts in a hash
daphnegold Oct 9, 2015
a58e065
Fixed a typo in MoneyMarketAccount class
daphnegold Oct 9, 2015
ef38cda
Fixed some logic problems
daphnegold Oct 9, 2015
d2b2f12
Fixed logic for check fees and overdrafting beyond limit
daphnegold Oct 9, 2015
3721918
Account and CheckingAccount now work with constant FEE,MIN_BAL
daphnegold Oct 9, 2015
8afb988
All classes now use constants for FEE/MIN_BAL.
daphnegold Oct 9, 2015
e83ac84
Cleaned up useless withdraw methods, MMA child of Savings
daphnegold Oct 9, 2015
f1620fc
Added Colorize & Money Gems, increased information for users about ac…
daphnegold Oct 12, 2015
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
30 changes: 14 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -73,24 +73,23 @@ Create an `Account` class which should have the following functionality:
**Account ID** - (Fixnum) a unique identifier corresponding to an account
**Owner ID** - (Fixnum) a unique identifier corresponding to an owner

<!--
## Wave 3
Create a `SavingsAccount` class which should inherit behavior from the `Account` class. It should include updated logic with the following functionality:
- An updated `initialize` method:
- The initial balance cannot be less than $10. If it is, this will `raise` an `ArgumentError`
- An updated `withdraw` method:
Create a `SavingsAccount` class which should inherit behavior from the `Account` class. It should include the following updated functionality:
- The initial balance cannot be less than $10. If it is, this will `raise` an `ArgumentError`
- Updated withdrawal functionality:
- Each withdrawal 'transaction' incurs a fee of $2 that is taken out of the balance.
- Does not allow the account to go below the $10 minimum balance - Will output a warning message and return the original un-modified balance

It should include the following new methods:
It should include the following new method:
- `#add_interest(rate)`: Calculate the interest on the balance and add the interest to the balance. Return the **interest** that was calculated and added to the balance (not the updated balance).
- Input rate is assumed to be a percentage (i.e. 0.25).
- The formula for calculating interest is `balance * rate/100`
- Example: If the interest rate is 0.25% and the balance is $10,000, then the interest that is returned is $25 and the new balance becomes $10,025.

Create a `CheckingAccount` class which should inherit behavior from the `Account` class. It should include updated logic with the following functionality:
- `#withdraw(amount)`: The input amount gets taken out of the account as result of an ATM transaction. Each withdrawal 'transaction' incurs a fee of $1 that is taken out of the balance. Returns the updated account balance.
- Does not allow the account to go negative. Will output a warning message and return the original un-modified balance.
Create a `CheckingAccount` class which should inherit behavior from the `Account` class. It should include the following updated functionality:
- Updated withdrawal functionality:
- Each withdrawal 'transaction' incurs a fee of $1 that is taken out of the balance. Returns the updated account balance.
- Does not allow the account to go negative. Will output a warning message and return the original un-modified balance.
- `#withdraw_using_check(amount)`: The input amount gets taken out of the account as a result of a check withdrawal. Returns the updated account balance.
- Allows the account to go into overdraft up to -$10 but not any lower
- The user is allowed three free check uses in one month, but any subsequent use adds a $2 transaction fee
Expand All @@ -101,16 +100,15 @@ Create a `CheckingAccount` class which should inherit behavior from the `Account

## Optional:

Create a `MoneyMarketAccount` class with a minimum of 6 specs. The class should inherit behavior from the `Account` class.
Create a `MoneyMarketAccount` class which should inherit behavior from the `Account` class.
- A maximum of 6 transactions (deposits or withdrawals) are allowed per month on this account type
- `self.new(id, initial_balance)`: creates a new instance with the instance variable `id` and 'initial_balance' assigned
- The initial balance cannot be less than $10,000 - this will `raise` an `ArgumentError`
- `#withdraw(amount)`: The input amount gets taken out of the account as result of an ATM transaction. Returns the updated account balance.
- The initial balance cannot be less than $10,000 - this will `raise` an `ArgumentError`
- Updated withdrawal logic:
- If a withdrawal causes the balance to go below $10,000, a fee of $100 is imposed and no more transactions are allowed until the balance is increased using a deposit transaction.
- Each transaction will be counted against the maximum number of transactions
- `#deposit(amount)`. Returns the updated account balance.
- Updated deposit logic:
- Each transaction will be counted against the maximum number of transactions
- Exception to the above: A deposit performed to reach or exceed the minimum balance of $10,000 is not counted as part of the 6 transactions.
- `#add_interest(rate)`: Calculate the interest on the balance and add the interest to the balance. Return the interest that was calculated and added to the balance (not the updated balance). Note** This is the same as the `SavingsAccount` interest.
- `#add_interest(rate)`: Calculate the interest on the balance and add the interest to the balance. Return the interest that was calculated and added to the balance (not the updated balance).
- Note** This is the same as the `SavingsAccount` interest.
- `#reset_transactions`: Resets the number of transactions to zero
-->
93 changes: 61 additions & 32 deletions bank-accounts.rb
Original file line number Diff line number Diff line change
@@ -1,18 +1,22 @@
require 'csv'
require 'money'
require 'colorize'
I18n.enforce_available_locales = false

module Bank

class Owner

attr_accessor :id, :last, :first, :street, :city, :state
attr_accessor :id, :last, :first, :street, :city, :state, :accounts

def initialize(id, last, first, street, city, state)
def initialize(id, last, first, street = nil, city = nil, state = nil)
@id = id.to_i
@first = first
@last = last
@street = street
@city = city
@state = state
@accounts = {}
end

def self.all

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice job using the all within the find below in order to write the all logic only once

Expand All @@ -35,14 +39,42 @@ def self.find(id)
end
end

def self.master_list # Accounts and their respective owners in one big happy array
master_list = []
account_owners_csv = CSV.read("./support/account_owners.csv")

account_owners_csv.each do |row|
account = Bank::Account.find(row[0].to_i)
account_owner = self.find(row[1].to_i)

account_owner.accounts[:account] = account

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure if this is an appropriate use of hash since it seems like this could be assigned directly to an account variable rather than setting it with a key/value pair

master_list.push(account_owner)
account.owner = account_owner
end

return master_list
end

def self.find_owner(id) # Find an account from the master_list! Then you can do stuff with it! Yay!
master_list = self.master_list

found = master_list.find do |instance|
instance.id.to_i == id
end

return found
end

end

class Account
# @@id_variable = 1000

attr_reader :balance, :id, :date
attr_accessor :owner

FEE = 0
MIN_BAL = 0

def initialize(id, initial_balance, open_date = nil, owner = nil)
@id = id.to_i
@balance = initial_balance.to_i
Expand All @@ -51,22 +83,43 @@ def initialize(id, initial_balance, open_date = nil, owner = nil)
@date = DateTime.strptime(open_date, "%Y-%m-%d %H:%M:%S %z")
end
@owner = owner
@colors_array = [:red, :light_red, :green, :light_green, :yellow, :light_yellow, :blue, :light_blue, :magenta, :light_magenta, :cyan, :light_cyan]

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems like this would be good to set as a constant rather than an instance variable since I don't think the colors array will change


raise ArgumentError if @balance < 0
raise ArgumentError.new("You cannot open an account with a negative balance.") if @balance < 0
end

def withdraw(withdrawal)
if withdrawal <= @balance
@balance -= withdrawal
if withdrawal <= 0
print "You can only withdraw a positive amount. "

return @balance
end

if @balance - withdrawal - self.class::FEE >= self.class::MIN_BAL
@balance -= (withdrawal + self.class::FEE) if self.class != MoneyMarketAccount

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like that you used a single-line conditional here but it would be better to use the if else instead to save you from having the write a similar condition more than once

@balance -= withdrawal if self.class == MoneyMarketAccount

puts "___Withdrawal Receipt___".colorize(@colors_array[rand(0..@colors_array.length-1)])

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You could also use the sample method call to retrieve one random color

puts "You withdrew: #{Money.new(withdrawal, "USD").format}"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be good to set "USD" to a constant since you're using it throughout when you reference money

puts "Fees: #{Money.new(self.class::FEE, "USD").format}" if self.class != MoneyMarketAccount
puts "Your balance: #{Money.new(@balance, "USD").format}" if self.class != MoneyMarketAccount
else
print "You cannot withdraw more than is in your bank account. "
print "You cannot withdraw that amount. "
end

return @balance
end

def deposit(deposit_amt)
@balance += deposit_amt
if deposit_amt > 0
@balance += deposit_amt

puts "___Deposit Receipt___".colorize(@colors_array[rand(0..@colors_array.length-1)])
puts "You deposited: #{Money.new(deposit_amt, "USD").format}"
puts "Your balance: #{Money.new(@balance, "USD").format}"
else
print "You can only deposit a positive amount. "
end

return @balance
end
Expand All @@ -93,29 +146,5 @@ def self.find(id) # Find a particular account from accounts.csv and return its o
return found
end

def self.master_list # Accounts and their respective owners in one big happy array
master_list = []
account_owners_csv = CSV.read("./support/account_owners.csv")

account_owners_csv.each do |row|
account = self.find(row[0].to_i)
owner_of_account = Bank::Owner.find(row[1].to_i)

account.owner = owner_of_account
master_list.push(account)
end

return master_list
end

def self.find_account(id) # Find an account from the master_list! Then you can do stuff with it! Yay!
master_list = self.master_list

found = master_list.find do |instance|
instance.id.to_i == id
end

return found
end
end
end
4 changes: 4 additions & 0 deletions bank.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
require './bank-accounts.rb'
require './savings-account.rb'
require './checking-account.rb'
require './money-market-account.rb'
45 changes: 45 additions & 0 deletions checking-account.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
module Bank
class CheckingAccount < Account

FEE = 100

def initialize(id, initial_balance)
super

@checks = 0
puts "Thank you for opening a Checking Account with Daphne's Bank.".colorize(@colors_array[rand(0..@colors_array.length-1)])
puts "___Account Summary___".colorize(@colors_array[rand(0..@colors_array.length-1)])
puts "Account ID: #{@id}"
puts "Initial balance: #{Money.new(@balance, "USD").format}\n\n"
puts "Each withdrawal incurs a fee of $1 that is taken out of the balance. Checking accounts may not overdraw except for check withdrawals, which allow account holders to overdraw a maximum of $10. Account holders are allowed three free checks per month, but any subsequent use incurs a $2 transaction fee."
end

def withdraw_using_check(withdrawal)
if withdrawal <= 0
print "You can only withdraw a positive amount. "

return @balance
end

if (@balance - withdrawal < -1000 && @checks <= 3) || (@balance - withdrawal - 200 < -1000 && @checks > 3)
print "You cannot overdraft your account more than $10. "
else
@balance -= withdrawal
@checks += 1
@balance -= 200 if @checks > 3
puts "___Check Withdrawal Receipt___".colorize(@colors_array[rand(0..@colors_array.length-1)])
puts "You withdrew: #{Money.new(withdrawal, "USD").format}"
puts "Number of checks this period: #{@checks}"
puts "Fees: #{Money.new(200, "USD").format}" if @checks > 3
puts "Your balance: #{Money.new(@balance, "USD").format}"

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like this same section Money.new(val, "USD").format is used several times so it may be a potential use of a method to be able to print this out the way you expect

end

return @balance
end

def reset_checks
@checks = 0
end

end
end
62 changes: 62 additions & 0 deletions money-market-account.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
module Bank
class MoneyMarketAccount < SavingsAccount

attr_reader :transactions

FEE = 10000

def initialize(id, initial_balance)
super

@transactions = 0
@lock = false
raise ArgumentError.new("Money Market Accounts require a minimum initial balance of $10,000.") if @balance < 1000000

puts "Thank you for opening a Money Market Account with Daphne's Bank.".colorize(@colors_array[rand(0..@colors_array.length-1)])
puts "___Account Summary___".colorize(@colors_array[rand(0..@colors_array.length-1)])
puts "Account ID: #{@id}"
puts "Initial balance: #{Money.new(@balance, "USD").format}\n\n"
puts "A maximum of 6 transactions (deposits or withdrawals) are allowed per month. If a withdrawal causes the balance to go below $10,000, a fee of $100 is imposed and no more transactions are allowed until the balance is increased using a deposit transaction. A deposit performed to reach or exceed the minimum balance of $10,000 is not counted as part of the 6 transactions."
end

def withdraw(withdrawal)
if @transactions < 6 && @lock == false
@transactions += 1 if withdrawal + 10000 <= @balance && withdrawal > 0

super
if @balance < 1000000
@balance -= 10000
@lock = true
puts "Fees: #{Money.new(self.class::FEE, "USD").format}"
end
puts "Your balance: #{Money.new(@balance, "USD").format}" if withdrawal > 0
puts "Transactions this period: #{@transactions}"
else
print "Your account is locked until your balance is restored to $10,000. " if @lock

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like you use these same print statements more than once so it might make sense to put them in a common method

print "You have reached your maximum of 6 transactions this month. " if @lock == false
end

return @balance
end

def deposit(deposit_amt)
@lock = false if deposit_amt + @balance > 1000000

if @transactions < 6 && @lock == false

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since you're using a boolean condition it would be a good place to try !@lock

@transactions += 1 if @balance >= 1000000 && deposit_amt > 0
super
puts "Transactions this period: #{@transactions}"
else
print "Your account is locked until your balance is restored to $10,000. " if @lock
print "You have reached your maximum of 6 transactions this month. " if @lock == false
end

return @balance
end

def reset_transactions
@transactions = 0
end

end
end
33 changes: 33 additions & 0 deletions savings-account.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
module Bank
class SavingsAccount < Account

FEE = 200
MIN_BAL = 1000


def initialize(id, initial_balance)
super

raise ArgumentError.new("Savings Accounts require a minimum initial balance of $1,000.") if @balance < 1000

if self.class != MoneyMarketAccount
puts "Thank you for opening a Savings Account with Daphne's Bank.".colorize(@colors_array[rand(0..@colors_array.length-1)])
puts "___Account Summary___".colorize(@colors_array[rand(0..@colors_array.length-1)])
puts "Account ID: #{@id}"
puts "Initial balance: #{Money.new(@balance, "USD").format}\n\n"
puts "Each withdrawal incurs a fee of $2 that is taken out of the balance. Account holders must maintain a minimum balance of $10, without exception."
end
end

def add_interest(rate)
interest = @balance * rate/100
@balance += interest
puts "___Interest Receipt___".colorize(@colors_array[rand(0..@colors_array.length-1)])
puts "Interest accrued: #{Money.new(interest, "USD").format}"
puts "Your balance: #{Money.new(@balance, "USD").format}"

return interest
end

end
end