diff --git a/README.md b/README.md index 25fd4d2a..b6e5c7b2 100644 --- a/README.md +++ b/README.md @@ -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 - diff --git a/bank.rb b/bank.rb index 5bdd3ad3..1804de38 100644 --- a/bank.rb +++ b/bank.rb @@ -1,195 +1,7 @@ -require 'csv' -require 'pry' - -module Bank - class Account - - attr_reader :balance, :id - attr_accessor :owner - - def initialize(id, initial_balance, open_date) - @id = id.to_i - @balance = initial_balance.to_i/100.0 - @open_date = DateTime.strptime(open_date, "%Y-%m-%d %H:%M:%S %z") - #@owner = nil - - # Raises an argument error if the initial balance is less than 0 - if initial_balance.to_i < 0 - raise ArgumentError, "The balance cannot be less than 0." - end - end - - # Creates accounts from the accounts.csv file - def self.all - @accounts = [] - accounts_csv = CSV.read("support/accounts.csv") - accounts_csv.each do |id, balance, date| - id = Bank::Account.new(id,balance,date) - @accounts.push(id) - end - #puts @accounts - return @accounts - end - - # Finds the account with the ID that matches the passed parameter and returns the instance - def self.find(id_search) - found = @accounts.find do |account| - account.id == id_search - end - return found - end - - # Links owners with accounts - def self.link_owner - self.all - Bank::Owner.all - accounts_with_owners = [] - account_owners_csv = CSV.read("support/account_owners.csv") - account_owners_csv.each do |row| - account = self.find(row[0].to_i) - owner_account = Bank::Owner.find(row[1].to_i) - account.owner = owner_account - accounts_with_owners.push(account) - end - return accounts_with_owners - end - - # ----------------------------------------- # - # Work below is extra # - - # Displays (with formatting) the account details for all the accounts in accounts.csv - # (Made this on accident and didn't want to let it go to waste!) - def self.all_print_nice - if @accounts == nil - puts "There are no accounts." - else - @accounts.each do |account| - puts account - account.current_balance - end - end - return - end - - # Finds an account by id passed in as a parameter and displays the account information nicely formatted - # (Made this on accident and didn't want to let it go to waste!) - def self.find_and_display(id_search) - found = @accounts.find do |account| - account.id == id_search - end - return found.current_balance - end - # end of extra work # -# ----------------------------------------# - - # Method for withdrawing from account - def withdraw(amount_to_withdraw) - # Checks that the user is not withdrawing more than what is available in the account - if (@balance - amount_to_withdraw)< 0 - puts "The requested withdrawal is more than the available funds." - puts "You only have $#{@balance} available for withdrawal." - return @balance - else - # makes the withdrawal and displays info to the user - @balance -= amount_to_withdraw - puts "You have withdrawn $#{amount_to_withdraw}." - puts "Your current balance is $#{@balance}" - return @balance - end - end - - # Method for depositing into account - def deposit(amount_to_deposit) - # Makes the deposit and displays info to the user - @balance += amount_to_deposit - puts "You have deposited $#{amount_to_deposit}." - puts "Your current balance is $#{@balance}." - return @balance - end - - # Displays current balance in the account - def current_balance - puts "The account with ID #{@id} currently has a balance of $#{@balance}." - puts "This account was set up on #{@open_date}" - end - - - end - - class Owner - attr_reader :first_name, :last_name, :street, :city, :state, :id - - def initialize(owner_hash) - @id = owner_hash[:id] - @first_name = owner_hash[:first_name] - @last_name = owner_hash[:last_name] - @street_address = owner_hash[:street_address] - @city = owner_hash[:city] - @state = owner_hash[:state] - end - - # Method to display details of an owner instance - def print_owner_details - puts "The owner of this account is #{@first_name} #{@last_name}." - puts "Street: #{@street_address}" - puts "City: #{@city}" - puts "State: #{@state}" - end - - # Creates accounts from the accounts.csv file - def self.all - owner_hash = Hash.new - @owners = [] - owners_csv = CSV.read("support/owners.csv") - owners_csv.each do |id, last_name, first_name, street_address, city, state| - owner_hash[:id] = id.to_i - owner_hash[:last_name] = last_name - owner_hash[:first_name] = first_name - owner_hash[:street_address] = street_address - owner_hash[:city] = city - owner_hash[:state] = state - id = Bank::Owner.new(owner_hash) - @owners.push(id) - end - puts @owners - return @owners - end - - # Finds the owner with the ID that matches the passed parameter and returns the instance - def self.find(id_search) - found = @owners.find do |owner| - owner.id == id_search - end - return found - end - - -# ----------------------------------------- # - # Work below is extra # - - # Displays (with formatting) the owner details for all the accounts in owners.csv - def self.all_print_nice - if @owners == nil - puts "There are no accounts." - else - @owners.each do |owner| - owner.print_owner_details - end - end - return - end - - # Finds an owner by id passed in as a parameter and displays the owner information nicely formatted - def self.find_and_display(id_search) - found = @owners.find do |owner| - owner.id == id_search - end - return found.print_owner_details - end - - # end of extra work # -# ----------------------------------------# - - end - -end +# Master bank file +# Requires all the seperate class files for Bank Accounts +require './lib/account.rb' +require './lib/owner.rb' +require './lib/savings_account.rb' +require './lib/checking_account.rb' +require './lib/money_market_account.rb' diff --git a/lib/account.rb b/lib/account.rb new file mode 100644 index 00000000..5a3a6272 --- /dev/null +++ b/lib/account.rb @@ -0,0 +1,168 @@ +require 'csv' +#require './lib/owner.rb' + +module Bank + class Account + + attr_reader :balance, :id + attr_accessor :owner, :min_balance, :fee, :acct_type, :allowed_to_withdraw + + + def initialize(id, initial_balance, open_date) + @id = id + @balance = initial_balance.to_f.round(2) + @open_date = open_date + @min_balance = 0 + @fee = 0 + @owner = nil + + # Raises an argument error if the initial balance is less than 0 + if initial_balance.to_f < @min_balance + raise ArgumentError, "The balance cannot be less than 0." + end + end + + # Creates accounts from the accounts.csv file + def self.all + @accounts = [] + accounts_csv = CSV.read("support/accounts.csv") + # For each line in accounts pass the id, balance, and date (formatted as need be) into a new Bank Account object + accounts_csv.each do |id, balance, date| + balance = balance.to_f.round(2)/100 + date = DateTime.strptime(date, "%Y-%m-%d %H:%M:%S %z") + id = Bank::Account.new(id, balance ,date) + # Push the new account into the @accounts array + @accounts.push(id) + end + return @accounts + end + + # Finds the account with the ID that matches the passed parameter and returns the instance + def self.find(id_search) + # Looks in @accounts array for a matching ID value + found = @accounts.find do |account| + account.id == id_search.to_s + end + return found + end + + # Links owners with accounts + def self.link_owner + # Creates Account and Owner arrays (calls Account and Owner self.all methods) + self.all + Bank::Owner.all + accounts_with_owners = [] + account_owners_csv = CSV.read("support/account_owners.csv") + # for each row in the + account_owners_csv.each do |row| + account = self.find(row[0]) + owner_account = Bank::Owner.find(row[1].to_i) + account.owner = owner_account + accounts_with_owners.push(account) + end + return accounts_with_owners + end + + # ----------------------------------------- # + # Work below is extra # + + # Displays (with formatting) the account details for all the accounts in accounts.csv + # (Made this on accident and didn't want to let it go to waste!) + def self.all_print_nice + if @accounts == nil + puts "There are no accounts." + else + @accounts.each do |account| + puts account + account.current_balance + end + end + return + end + + # Finds an account by id passed in as a parameter and displays the account information nicely formatted + # (Made this on accident and didn't want to let it go to waste!) + def self.find_and_display(id_search) + found = @accounts.find do |account| + account.id == id_search.to_s + end + return found.current_balance + end + # end of extra work # +# ----------------------------------------# + + # Method for withdrawing from account + def withdraw(orig_amount_to_withdraw) + amount_to_withdraw = orig_amount_to_withdraw + @fee + # check if the requested withdrawal is more than the minimum balance + if (@balance - amount_to_withdraw) < @min_balance + # If we are dealing with a MoneyMarket account, we do special withdrawal behavior + # Keeping this here instead of in Money Market prevented us from having to rewrite an entire withdraw function for Money Market (we can just super the Account method) + if @acct_type == "MoneyMarket" + # Checks that the withdrawal won't put you below 0 or if you are no longer allowed to withdraw + if (@balance - amount_to_withdraw - @money_market_fee) < 0 || @allowed_to_withdraw == false + puts "Sorry you cannot make that withdrawal without depositing more money." + else + # If the withdrawal goes below min balance a fee is imposed and no further withdrawals are permitted + puts "As this transaction puts your balance below $#{@min_balance.round(2)}, a fee of $#{@money_market_fee.round(2)} has been imposed." + @balance -= (amount_to_withdraw + @money_market_fee) + puts "Your balance is $#{@balance.round(2)}" + @allowed_to_withdraw = false + end + else + # If account is not Money Market, normal withdrawal behavior for attempting to withdraw too much + puts "The requested withdrawal is more than the available funds." + # Works for all account types, min balance and fee vary by account type + if (@balance-@min_balance-@fee) < 0 + puts "You have no money left to withdraw." + else + puts "You only have $#{(@balance-@min_balance-@fee).round(2)} available for withdrawal." + end + end + return @balance + else + # makes the withdrawal and displays info to the user + @balance -= (amount_to_withdraw) + puts "You have withdrawn $#{orig_amount_to_withdraw.round(2)}" + if @fee != 0 + puts "You have also incurred a $#{@fee.round(2)} fee." + end + puts "Your current balance is $#{@balance.round(2)}" + return @balance + end + end + + + # Method for depositing into account + def deposit(amount_to_deposit) + # Makes the deposit and displays info to the user + @balance += amount_to_deposit + puts "You have deposited $#{amount_to_deposit.round(2)}." + puts "Your current balance is $#{@balance.round(2)}." + # Special case to allow Money Market account to make withdrawals again + if @acct_type == "MoneyMarket" && @balance > min_balance + @allowed_to_withdraw = true + end + return @balance + end + + # Displays current balance in the account + def current_balance + puts "The account with ID #{@id} currently has a balance of $#{@balance.round(2)}." + puts "This account was set up on #{@open_date}" + end + + def add_interest(rate) + # Add interest only runs for the MoneyMarket and Savings account + if @acct_type == "MoneyMarket" || @acct_type == "Savings" + interest = @balance * rate/100 + @balance += interest + puts "After adding interest, the balance is now $#{@balance.round(2)}" + return interest + else + puts "This type of account does not accumulate interest." + end + end + + end +end diff --git a/lib/checking_account.rb b/lib/checking_account.rb new file mode 100644 index 00000000..1dec7b4b --- /dev/null +++ b/lib/checking_account.rb @@ -0,0 +1,50 @@ +module Bank + + class CheckingAccount < Account + + def initialize(id, initial_balance, open_date) + super + @fee = 1.0 + @check_number = 1 + end + + # CheckingAccount uses the withdraw method from Account + # This method does not need to be called here, but is left in for clarity + def withdraw(amount_to_withdraw) + super + end + + def withdraw_using_check(amount_to_withdraw) + initial_balance = @balance + # min_balance is set to -10 for check withdrawals + @min_balance = -10 + # If the customer has used fewer than 3 checks, the fee is set to 0, and the withdraw method from Account is run + if @check_number <= 3 + @fee = 0 + withdraw(amount_to_withdraw) + # If a successful withdrawal was made, the check number is incremented + if @balance != initial_balance + @check_number +=1 + end + else + # If the user has used more than 3 checks, the fee is updated and the withdraw method from Account is run + @fee = 2.0 + withdraw(amount_to_withdraw) + # If a successul withdrawal was made the check number is incremented + if @balance != initial_balance + @check_number +=1 + end + end + # Resets min_balance and fee to the defaults in initialize (necessary for normal withdraw method to function as expected) + @min_balance = 0 + @fee = 1.0 + return @balance + end + + # Resets @check_number variable to allow more withdrawals using check + def reset_checks + @check_number = 0 + end + + end +end diff --git a/lib/money_market_account.rb b/lib/money_market_account.rb new file mode 100644 index 00000000..ace30132 --- /dev/null +++ b/lib/money_market_account.rb @@ -0,0 +1,58 @@ +module Bank + + class MoneyMarketAccount < Account + # Money market has two fees - the normal withdrawal fee (@fee) and the fee assessed when the balance goes below 10_000 (@money_market_fee) + # Money Market has a transactions variable to keep track of the numer of transactions for the month (no other account has this) + def initialize(id, initial_balance, open_date) + super + @transactions = 0 + @min_balance = 10000.00 + @fee = 0 + @money_market_fee = 100.00 + @acct_type = "MoneyMarket" + + # Check that the initial balance is above min_balance + if initial_balance.to_f < @min_balance + raise ArgumentError, "The balance cannot be less than $#{@min_balance}." + end + end + + + def withdraw(amount) + # If you have made more than 6 transactions, the transaction will not go through + if @transactions >= 6 + puts "You cannot make any more transactions this month." + else + # If you have made fewer than 6 transactions, MoneyMarket uses the Account withdraw method and increments @transactions + super + @transactions += 1 + end + end + + def deposit(amount) + # If the balance is below min balance, the user can make a deposit even if they have hit max transactions + if @balance < @min_balance + super + # If the balance is not below min balance and the user has made more than 6 transactions, the transaction will not go through + elsif @transactions >= 6 + puts "You cannot make any more transactions this month." + else + # If the balace is above min balance and the transactions are below 6, MoneyMarket uses the Account deposit method and increments @transactions + super + @transactions += 1 + end + end + # The MoneyMarket account calls the add_interest method directly from Accounts + # This line is not necessary, but it being kept in for clarity + def add_interest(rate) + super + end + + # Method to reset the @transactions variabale and allow additional transactions + def reset_transactions + @transactions = 0 + @allowed_to_withdraw = true + end + + end +end diff --git a/lib/owner.rb b/lib/owner.rb new file mode 100644 index 00000000..af4616f9 --- /dev/null +++ b/lib/owner.rb @@ -0,0 +1,79 @@ +module Bank + +class Owner + attr_reader :first_name, :last_name, :street, :city, :state, :id + + def initialize(owner_hash) + @id = owner_hash[:id] + @first_name = owner_hash[:first_name] + @last_name = owner_hash[:last_name] + @street_address = owner_hash[:street_address] + @city = owner_hash[:city] + @state = owner_hash[:state] + end + + # Method to display details of an owner instance + def print_owner_details + puts "The owner of this account is #{@first_name} #{@last_name}." + puts "Street: #{@street_address}" + puts "City: #{@city}" + puts "State: #{@state}" + end + + # Creates accounts from the accounts.csv file + def self.all + owner_hash = Hash.new + @owners = [] + owners_csv = CSV.read("support/owners.csv") + owners_csv.each do |id, last_name, first_name, street_address, city, state| + owner_hash[:id] = id.to_i + owner_hash[:last_name] = last_name + owner_hash[:first_name] = first_name + owner_hash[:street_address] = street_address + owner_hash[:city] = city + owner_hash[:state] = state + id = Bank::Owner.new(owner_hash) + @owners.push(id) + end + puts @owners + return @owners + end + + # Finds the owner with the ID that matches the passed parameter and returns the instance + def self.find(id_search) + found = @owners.find do |owner| + owner.id == id_search + end + return found + end + + +# ----------------------------------------- # + # Work below is extra # + + # Displays (with formatting) the owner details for all the accounts in owners.csv + def self.all_print_nice + if @owners == nil + puts "There are no accounts." + else + @owners.each do |owner| + owner.print_owner_details + end + end + return + end + + # Finds an owner by id passed in as a parameter and displays the owner information nicely formatted + def self.find_and_display(id_search) + found = @owners.find do |owner| + owner.id == id_search + end + return found.print_owner_details + end + + # end of extra work # +# ----------------------------------------# + +end + +end diff --git a/lib/savings_account.rb b/lib/savings_account.rb new file mode 100644 index 00000000..ef972f88 --- /dev/null +++ b/lib/savings_account.rb @@ -0,0 +1,31 @@ +module Bank + class SavingsAccount < Account + + def initialize(id, initial_balance, open_date) + super + @min_balance = 10.0 + @fee = 2.0 + # Acct_type variable allows add_interest method from Account to function correctly for Savings Account + @acct_type = "Savings" + + #Raises an argument error if the initial balance is less than 0 + if initial_balance.to_f < @min_balance + raise ArgumentError, "The balance cannot be less than $#{@min_balance.round(2)}." + end + end + + # Savings Account uses the withdraw method from Account + # This line could come out but is being kept in for clarity. + def withdraw(orig_amount_to_withdraw) + super + end + + # Savings Account uses the add_interest method from Account + # This line could come out but is being kept in for clarity. + def add_interest(rate) + super + end + + + end +end diff --git a/bank_interaction.rb b/retired/bank_interaction.rb similarity index 100% rename from bank_interaction.rb rename to retired/bank_interaction.rb