Thursday, February 15, 2018

Programming Challenge 15.14 - Bank Accounts

Example Files: BankAccounts.7z


Account.h


#ifndef ACCOUNT_H_
#define ACCOUNT_H_

#include <iosfwd>

class Account
{
    protected:
        double beginningBalance;
        double balance;
        double annualRate;
        double monthlyRate;
        double monthlyInterest;
        double withdrawalTotal;
        double depositTotal;
        double monthlyCharges;
        double chargesTotal;
        int    numDeposits;
        int     numWithdrawals;

    public:
        Account()
        { }

        Account(double, double);

        virtual ~Account() = 0;

        // Mutator functions
        virtual void   deposit(const double &);
        virtual void   withdraw(const double &);
        virtual double calcInt();
        virtual void   monthlyProc();

        // Accessor functions
        double getBalance() const
        { return balance; }

        int getNumDeposits() const
        { return numDeposits; }

        int getNumWithdrawals() const
        { return numWithdrawals; }

        // Overloaded ostream operator
        friend std::ostream &operator << (std::ostream &, Account &);
};

#endif

Account.cpp


#include "Account.h"

#include <iomanip>
using std::setprecision;

#include <iostream>
using std::cout;
using std::fixed;

/* **********************************************************
            Account::Account() : Constructor
    ********************************************************** */

Account::Account(double initBalance, double rate) :
                      beginningBalance(initBalance), annualRate(rate)
{
    balance = beginningBalance;
   
    monthlyRate = 0.0;
    monthlyInterest = 0.0;
    depositTotal = 0.0;
    withdrawalTotal = 0.0;
    monthlyCharges = 0.0;
    chargesTotal = 0.0;
    numDeposits = 0;
    numWithdrawals = 0;
}

/* **********************************************************
            v Account::~Account() - Destructor
   ********************************************************** */

Account::~Account()
{
}

/* **********************************************************
            v Account::deposit() : const double &
    The amount value passed to this function is added to both
    balance and deposit total members. The function then
    increments the numDeposits variable.
   ********************************************************** */

void Account::deposit(const double &amount)
{
    balance += amount;

    depositTotal += amount;
    numDeposits++;
}

/* **********************************************************
            v Account::withdraw() : const double &
    The amount value passed to this function is deducted from
    the balance member, and assigned to the withdrawalTotal
    member. The function then increments the numWithdrawals
    variable.
   ********************************************************** */

void Account::withdraw(const double &amount)
{
    balance -= amount;

    withdrawalTotal += amount;
    numWithdrawals++;
}

/* **********************************************************
            v Account::monthlyProc()
    The monthly charges are deducted from the balance member,
    then the member function calcInt() is called to calculate
    the interest earned. This value is added to the balance
    member. In a final step, the monthly charges, number of
    withdrawals and number of deposits are reset to 0.
   ********************************************************** */

void Account::monthlyProc()
{
    balance -= monthlyCharges;
    balance += calcInt();

    chargesTotal += monthlyCharges;

    monthlyCharges = 0.0;
    numWithdrawals = 0;
    numDeposits = 0;
}

/* **********************************************************
            v d Account::calcInt()
    This function calculates the monthly interest rate. This
    value is returned to the caller.
   ********************************************************** */

double Account::calcInt()
{
    monthlyRate = annualRate / 12;
    monthlyInterest = balance * (monthlyRate / 100.0);

    return monthlyInterest;
}

/* **********************************************************
            Overloaded ostream operator <<
    Outputs the account information.
   ********************************************************** */

std::ostream &operator << (std::ostream &out, Account &account)
{
    out << setprecision(2) << fixed;
    out << "Beginning Balance:        $ " << account.beginningBalance << "\n";
    out << "Total Amount Deposits:    $ " << account.depositTotal << "\n";
    out << "Total Amount Withdrawals: $ " << account.withdrawalTotal << "\n\n";
    out << "Total Interest Earned:    $ " << account.monthlyInterest << "\n";
    out << "Total Service Charges:    $ " << account.chargesTotal << "\n";
    out << "Ending Balance:           $ " << account.balance << "\n\n";

    return out;
}

SavingsAccount.h


#ifndef SAVINGS_ACCOUNT_H_
#define SAVINGS_ACCOUNT_H_

#include "Account.h"

class SavingsAccount : public Account
{
    private:
        const double MIN_BALANCE = 25.0;
        const int    NUM_FREE_WITHDRAWALS = 4;

        bool status;

    public:
        SavingsAccount()
        {
        }

        SavingsAccount(double, double);

        virtual ~SavingsAccount()
        {
        }

        bool accountStatus(const double &);

        virtual void deposit(const double &)  override;
        virtual void withdraw(const double &) override;
        virtual void monthlyProc()            override;
};

#endif

SavingsAccount.cpp


#include "SavingsAccount.h"

#include <iostream>
using std::cout;

/* **********************************************************
            SavingsAccount::SavingsAccount() : Constructor -
                                                          double, double
   ********************************************************** */

SavingsAccount::SavingsAccount(double initBalance, double rate) :
        Account(initBalance, rate)
{
    status = false;
}

/* **********************************************************
            b SavingsAccount::accountStatus() : const double &
    This function sets and returns the account status.
   ********************************************************** */

bool SavingsAccount::accountStatus(const double &amount)
{
    if (balance >= MIN_BALANCE || balance + amount >= MIN_BALANCE)
    {
        status = true;
    }
    else if (balance < MIN_BALANCE)
    {
        status = false;
    }

    return status;
}

/* **********************************************************
           v SavingsAccount::deposit() : const double &
    This function first determines whether the amount value is
    greater than 0.0, then calls the accountStatus() function
    to determine the account status. Next, the Account class's
    deposit function is called and the amount is passed to it.
    If the status returns negative, or an insufficient or a
    negative amount is detected, an appropriate error message
    is output before the function exits.
   ********************************************************** */

void SavingsAccount::deposit(const double &amount)
{
    if (amount > 0.0)
    {
        if (accountStatus(amount) == true)
        {
            Account::deposit(amount);
        }
        else
        {
            cout << "Account Inactive: Insufficient Balance!\n";
        }
    }
    else
    {
        cout << "Transaction Canceled: Insufficient/Negative Amount!\n";
    }
}

/* **********************************************************
            v SavingsAccount::withdraw() : const double &
    This function first determines whether the amount passed
    to it is greater than 0. If it is, the function determines
    whether the account status is active. If it is, the base
    class's withdraw() member function is called and the
    amount value passed to it. If either the value is below
    or equal to 0, the balance, after deducting the amount
    falls below the MIN_BALANCE, or the amount is higher than
    the balance, appropriate messages are output to inform
    the customer, before the function exits.
   ********************************************************** */

void SavingsAccount::withdraw(const double &amount)
{
    if (amount > 0.0)
    {
        if (status == true && amount <= balance)
        {
            Account::withdraw(amount);
        }
        else if (accountStatus(balance - amount) == false)
        {
            cout << "Account Inactive: Insufficient Balance!\n";
        }
        else
        {
            cout << "Transaction Canceled: Withdrawal Amount Exceeds Account Balance!\n";
        }
    }
    else
    {
        cout << "Transaction Canceled: Negative Amount!\n";
    }
}

/* **********************************************************
            v SavingsAccount::monthlyProc()
    This function calculates the monthly charges. If the
    number of withdrawals is greater than the number of free
    transactions (4), the service charge is calculated and
    assigned to the base class's member variable, before the
    base class's monthlyProc() function is called.
   ********************************************************** */

void SavingsAccount::monthlyProc()
{
    if (getNumWithdrawals() > NUM_FREE_WITHDRAWALS)
    {
        monthlyCharges = 1.0 * (getNumWithdrawals() - NUM_FREE_WITHDRAWALS);       
    }   

    Account::monthlyProc();
}

CheckingAccount.h


#ifndef CHECKING_ACCOUNT_H_
#define CHECKING_ACCOUNT_H_

#include "Account.h"

class CheckingAccount : public Account
{
    private:
        const double MONTHLY_FEE = 5.0;
        const double SERVICE_FEE = 15.0;
        const double WITHDRAWAL_FEE = 0.10;

    public:
        CheckingAccount()
        {
        }

        CheckingAccount(double, double);

        virtual ~CheckingAccount()
        {
        }

        virtual void deposit(const double &)  override;
        virtual void withdraw(const double &) override;
        virtual void monthlyProc()               override;
};

#endif

CheckingAccount.cpp


#include "CheckingAccount.h"

#include <iostream>
using std::cout;

/* **********************************************************
            CheckingAccount::CheckingAccount() : Constructor -
                                                             double, double
   ********************************************************** */

CheckingAccount::CheckingAccount(double initBalance, double rate) :
          Account(initBalance, rate)
{
}

/* **********************************************************
            v CheckingAccount::deposit() : const double &
    If the amount value is greater than 0, the base class's
    deposit() member function is called, and the amount is
    passed to it. Else an appropriate message is output, to
    inform the customer that the transaction could not be
    completed.
   ********************************************************** */

void CheckingAccount::deposit(const double &amount)
{
    if (amount > 0.0)
    {
        Account::deposit(amount);
    }
    else
    {
        cout << "Transaction Canceled: Insufficient/Negative Amount!\n";
    }
}

/* **********************************************************
            v CheckingAccount::withdraw() : const double &
    First, this function determines whether the amount value
    is greater than 0.0. If it is, and balance - amount causes
    the balance to go below 0.0, the withdrawal amount plus a
    service fee are passed to the base class's withdraw()
    member function. If this isn't the case, only the amount
    value is passed to it. In case the balance is already
    below 0.0, or the value passed to this function is 0.0, an
    appropriate message is output to inform the customer.
   ********************************************************** */

void CheckingAccount::withdraw(const double &amount)
{
    if (amount > 0.0)
    {
        if (balance > 0.0)
        {
            if (balance - amount < 0.0)
            {
                Account::withdraw(amount + SERVICE_FEE);
            }
            else
            {
                Account::withdraw(amount);
            }
        }
        else
        {
            cout << "Transaction Canceled: Insufficient Account Balance!\n";
        }
    }
    else
    {
        cout << "Transaction Canceled: Insufficient/Negative Amount!\n";
    }
}

/* **********************************************************
            v CheckingAccount::monthlyProc()
    This function calculates and assigns the services charges
    for to the base class's monthlyCharges member, before the
    base class's monthlyProc() function is called.
   ********************************************************** */

void CheckingAccount::monthlyProc()
{
    monthlyCharges = MONTHLY_FEE + (WITHDRAWAL_FEE * getNumWithdrawals());

    Account::monthlyProc();
}

Menu.h


#ifndef MENU_H_
#define MENU_H_

#include "SavingsAccount.h"
#include "CheckingAccount.h"

class Menu
{
    private:
        char   option;
        char   accountType;
        double amount;

    public:
        Menu();

        void displayMenuItems() const;
        void displayAccountTypes() const;
        void displayAccountOptions() const;
        bool isValidOption(const char &);
        void mainMenu();
        void accountTransaction();
        void printAccountInfo() const;
};

#endif

Menu.cpp


#include "Menu.h"

#include <iostream>
using std::cin;
using std::cout;

enum MenuItems
{
    SELECT_ACC_TYPE = 'T', DEPOSIT = 'D', WITHDRAW = 'W',
    PRINT_ACCOUNT_INFO = 'P', QUIT = 'Q'
};

enum AccountType
{
    SAVINGS_ACCOUNT = 'S', CHECKING_ACCOUNT = 'C'
};

enum InfoType
{
    CURRENT_BALANCE = 'B', MONTHLY_INFO = 'M'
};

static SavingsAccount savings(25.0, 10.0);
static CheckingAccount checking(100.0, 1.75);

/* **********************************************************
            Menu::Menu() - Constructor
   ********************************************************** */

Menu::Menu()
{
    option = ' ';
    accountType = ' ';
    amount = 0.0;
}

/* **********************************************************
            Menu::displayMenuItems()
    This function outputs all available menu options.
   ********************************************************** */

void Menu::displayMenuItems() const
{
    cout << "ASHIKAGA BANK - CUSTOMER ACCOUNT MENU\n\n";
    cout << "[T] Select Account Type\n";
    cout << "[D] Deposit\n";
    cout << "[W] Withdraw\n";
    cout << "[P] Print Account Information\n";
    cout << "[Q] Quit Program\n\n";
    cout << "SELECT OPTION: ";
}

/* **********************************************************
            Menu::displayAccountTypes()
    This function outputs the account types, from which a
    customer must choose.
    ********************************************************** */

void Menu::displayAccountTypes() const
{
    cout << "ACCOUNT TYPE:\n";
    cout << "[S] Savings Account\n";
    cout << "[C] Checking Account\n\n";
    cout << "SELECT OPTION: ";
}

/* **********************************************************
            Menu::displayAccountOptions()
    This function allows the customer to select, which account
    info he or she wishes to view.
   ********************************************************** */

void Menu::displayAccountOptions() const
{
    cout << "ACCOUNT INFORMATION:\n";
    cout << "[B] Current Balance\n";
    cout << "[M] Monthly Statement\n\n";
    cout << "SELECT OPTION: ";
}

/* **********************************************************
            Menu::mainMenu()
    This function acts as the main menu, from which all other
    functions of this class are called.
   ********************************************************** */

void Menu::mainMenu()
{
    do
    {
        displayMenuItems();
        cin >> option;
        cout << "\n";

        if (isValidOption(toupper(option)) == true)
        {
            switch (option)
            {
                case SELECT_ACC_TYPE:
                {
                    displayAccountTypes();
                    cin >> accountType;
                    cout << "\n";
                } break;

                case DEPOSIT:
                {
                    accountTransaction();
                } break;

                case WITHDRAW:
                {
                    accountTransaction();
                } break;

                case PRINT_ACCOUNT_INFO:
                {
                    if (accountType != ' ')
                    {
                        displayAccountOptions();
                        cin >> option;
                        cout << "\n";

                        if (isValidOption(toupper(option)) == true)
                        {
                            if (toupper(option) == CURRENT_BALANCE)
                            {
                                cout << "Current Balance: $ ";

                                accountType == SAVINGS_ACCOUNT ? cout << savings.getBalance() << "\n\n" :
                                                                  cout << checking.getBalance() << "\n\n";
                            }
                            else
                            {
                                printAccountInfo();
                            }
                        }
                    }
                    else
                    {
                        cout << "No Account Type Selected!\n\n";
                        displayAccountTypes();
                        cin >> accountType;
                        cout << "\n";
                    }
                } break;

                case QUIT:
                {
                    cout << "THE ASHIKAGA BANK THANKS YOU FOR YOUR TRUST AND PATRONAGE!";
                } break;
            }
        }
    } while (toupper(option) != QUIT);
}

/* **********************************************************
            b Menu::isValidOption() : const char &
    This function validates the input. The result is returned
    to the caller.
   ********************************************************** */

bool Menu::isValidOption(const char &choice)
{
    if (choice == 'T' || choice == 'C' || choice == 'D' || choice == 'W' ||
         choice == 'P' || choice == 'B' || choice == 'M' || choice == 'Q')
    {
        return true;
    }

    return false;
}

/* **********************************************************
            Menu::accountTransaction()
    This function asks the customer to enter a deposit or
    withdrawal amount. The value is passed to the appropriate
    class's deposit() or withdrawal() member function.
   ********************************************************** */

void Menu::accountTransaction()
{
    switch (option)
    {
        case DEPOSIT:
        {
            cout << "Please Enter Deposit Amount: $ ";
            cin >> amount;

            accountType == SAVINGS_ACCOUNT ? savings.deposit(amount) :
                                                        checking.deposit(amount);
            cout << "\n";
        } break;

        case WITHDRAW:
        {
            cout << "Please Enter Withdrawal Amount: $ ";
            cin >> amount;
            accountType == SAVINGS_ACCOUNT ? savings.withdraw(amount) :
                                                        checking.withdraw(amount);
            cout << "\n";
        } break;
    }
}

/* **********************************************************
           Menu::printAccountInfo() : obj &, obj &
    This function outputs the account type and account status.
    Before the account information is output, the monthly
    charges are calculated.
   ********************************************************** */

void Menu::printAccountInfo() const
{
    cout << "ASHIKAGA BANK - MONTHLY CUSTOMER ACCOUNT STATEMENT\n\n";
    cout << "Account Type:   ";
   
    accountType == SAVINGS_ACCOUNT ? cout << "SAVINGS ACCOUNT\n" :
                                                cout << "CHECKING ACCOUNT\n";
   
    if (accountType == SAVINGS_ACCOUNT && savings.getBalance() < 25.0 ||
         accountType == CHECKING_ACCOUNT && checking.getBalance() < 0.0)
    {
        cout << "Account Status: INACTIVE\n\n";
    }
    else
    {
        cout << "Account Status: ACTIVE\n\n";
    }

    cout << "NUMBER OF TRANSACTIONS:\n";
    cout << "Deposits:    # ";
    accountType == SAVINGS_ACCOUNT ? cout << savings.getNumDeposits() << "\n":
                                                cout << checking.getNumDeposits() << "\n";

    cout << "Withdrawals: # ";
    accountType == SAVINGS_ACCOUNT ? cout << savings.getNumWithdrawals() << "\n\n" :
                                                cout << checking.getNumWithdrawals() << "\n\n";

    accountType == SAVINGS_ACCOUNT ? savings.monthlyProc() :
                                                checking.monthlyProc();

    accountType == SAVINGS_ACCOUNT ? cout << savings << "\n" :
                                                cout << checking << "\n";
}

BankAccount.cpp


#include "Menu.h"

#include <iomanip>
using std::setprecision;

#include <iostream>
using std::cin;
using std::cout;
using std::fixed;

int main()
{
    Menu mMenu;
    mMenu.mainMenu();

    cin.get();
    cin.ignore();
    return 0;
}

Example Output:












No comments:

Post a Comment