Tuesday, November 25, 2014

Bank Account Lab


namespace BankersLibrary
{

    public enum TransactionType { Deposit, Withdraw, Transfer }
    [Serializable]
    public class Owner
    {
        // first last phone email
        private string _firstName;
        public string FirstName
        { get { return _firstName; } }

        private string _lastName;
        public string LastName
        { get { return _lastName; } }

        private string _phoneNumber;
        public string PhoneNumber
        { get { return _phoneNumber; } }

        private string _email;
        public string Email
        { get { return _email; } }

        public Owner(string fName, string lName, string pNumber, string email)
        {
            _firstName = fName;
            _lastName = lName;
            _phoneNumber = pNumber;
            _email = email;
        }
    }
    [Serializable]
    public class Transaction
    {
        // Define a class Transaction with fields _amount, _transactionDate, type(TransactionType)
        private decimal _amount;
        public decimal Amount
        { get { return _amount; } }

        private DateTime _transactionDate;
        public DateTime TransactionDate
        { get { return _transactionDate; } }

        private TransactionType _transactionType;
        public TransactionType TransactionType
        { get { return _transactionType; } }

        public Transaction(decimal amount, DateTime date, TransactionType type)
        {
            _amount = amount;
            _transactionDate = date;
            _transactionType = type;
        }
    }
    [Serializable]
    public abstract class BankAccount
    {
        // Define an abstract class BankAcount with fields _accountNumber, _balance, _dateCreated, _owner (of type List<Owner>)
        string _accountNumber;
        public string AccountNumber
        { get { return _accountNumber; } }

        private decimal _balance;
        public decimal Balance
        {
            get { return _balance; }
            internal protected set { _balance = value; }
        }

        private DateTime _dateCreated;
        public DateTime DateCreated
        { get { return _dateCreated; } }

        private List<Owner> _owner;
        public Owner[] Owner
        { get { return _owner.ToArray(); } }

        internal protected List<Transaction> _transactions;
        public Transaction[] TransactionList
        {
            get { return _transactions.ToArray(); }
        }

        // Add constructor \/ and properties ^
        public BankAccount(string accountNumber, decimal initialDeposit, DateTime todaysDate, Owner accountOwner)
        {
            _accountNumber = accountNumber;
            _balance = initialDeposit;
            _dateCreated = todaysDate;
            _owner = new List<Owner>();
            _owner.Add(accountOwner);
            _transactions = new List<Transaction>();
        }

        // Add instance methods: virtual Deposit, abstract Withdraw, AddOwner(Owner owner)
        public virtual decimal Deposit(decimal amount)
        {
            Transaction t = new Transaction(amount, DateTime.Now, TransactionType.Deposit);
            _transactions.Add(t);
            _balance += amount;
            return _balance;
        }

        public abstract bool Withdraw(decimal amount);

        public void AddOwner(Owner owner)
        {
            _owner.Add(owner);
        }

        // Add static methods: static Transfer
        /// <summary>
        /// Transfers a specified amount from the balance of account 1 to the balance of account 2.
        /// </summary>
        /// <param name="a1">The Account which contains the funds to be transfered from.</param>
        /// <param name="a2">The Account which will recieve the transfered funds</param>
        /// <param name="amount">The value in dollers which will be transfered</param>
        /// <returns></returns>
        public static bool TransferFunds(BankAccount a1, BankAccount a2, decimal amount)
        {
            if (a1._balance >= amount)
            {
                Transaction t = new Transaction(-1 * amount, DateTime.Now, TransactionType.Transfer);
                a1._transactions.Add(t);
                Transaction tr = new Transaction(amount, DateTime.Now, TransactionType.Transfer);
                a2._transactions.Add(tr);
                ///////////////////////////////////////////////////////////////////////////////////
                a2._balance += amount;
                a1._balance -= amount;
                return true;
            }
            return false;
        }
    }
    // Define a class CheckingAccount that inherits from BankAccount
    // add fields: _minBalance
    // Define its constructor, properties, methods
    [Serializable]
    public class CheckingAccount : BankAccount
    {
        private decimal _minimumBalance;
        public decimal MinimumBalance
        { get { return _minimumBalance; } }

        public CheckingAccount(string accountNumber, decimal initialDeposit, DateTime todaysDate, Owner accountOwner)
            : base(accountNumber, initialDeposit, todaysDate, accountOwner)
        {
            _minimumBalance = 500; // $500 required to open a checking account.

            if (initialDeposit < _minimumBalance)
                throw new Exception("Can not create an account without a deposit of $500 or more");
        }

        new public decimal Deposit(decimal amount)
        {
            return base.Deposit(amount);
        }

        public override bool Withdraw(decimal amount)
        {
            if (Balance - amount >= _minimumBalance)
            {
                Transaction t = new Transaction(amount, DateTime.Now, TransactionType.Withdraw);
                _transactions.Add(t);
                Balance -= amount;
                return true;
            }
            return false;
        }
    }
    // Define a class SavingsAccount that inherts from BankAccount
    // Add fields: _interestRate
    // Define its constructor, properties and methods.
    [Serializable]
    public class SavingsAccount : BankAccount
    {
        private decimal _interestRate;
        public decimal InterestRate
        { get { return _interestRate; } }


        public SavingsAccount(string accountNumber, decimal initialDeposit, DateTime todaysDate, Owner accountOwner)
            : base(accountNumber, initialDeposit, todaysDate, accountOwner)
        {
            _interestRate = 0.035m;
        }

        public override decimal Deposit(decimal amount)
        {
            Transaction t = new Transaction(amount, DateTime.Now, TransactionType.Deposit);
            _transactions.Add(t);
            Balance += amount;
            return Balance;
        }

        public override bool Withdraw(decimal amount)
        {
            if (Balance - amount >= 0)
            {
                Transaction t = new Transaction(amount, DateTime.Now, TransactionType.Withdraw);
                _transactions.Add(t);
                Balance -= amount;
                return true;
            }
            return false;
        }
    }
}
//====================================================================

using System.Windows.Forms;
using BankersLibrary;
using System.IO;

namespace BankAccount_Lab
{
    // Add UI to perform the following:
    // Be able to:
    //              Deposit money into account selected account
    //              Withdraw money from account selected account
    //              Transfer from one account to another
    //
    //              Provide account way to save all accounts to account file and read them back.
    public partial class Form1 : Form
    {
        ///<summary> Gloabl Variables:
        ///</summary>
        // Bank Account List to store all accounts and their activity/data.
        List<BankAccount> accountList = new List<BankAccount>();
        // This will act as the index of the previously selected account so it can be reselected when the display refreshes.
        int selectedAccountIndex;
        // file location for accountList
        string accountFileLocation = "accountList.dat";
        // Master Account Number Generator:
        int MASTER_ACCOUNT_ID;
        string Master_Account_ID_Location = "MasterAccountID.txt";
        bool bCloseNormally = true;

        /// <summary> Loading and Closing Events
        /// </summary>
        public Form1()
        {
            InitializeComponent(); // initializes the Form
        }
        private void Form1_Load(object sender, EventArgs e)
        {
            // Read and Load the master account ID
            if (File.Exists(Master_Account_ID_Location))
            {
                using (StreamReader sr = new StreamReader(Master_Account_ID_Location, true))
                {
                    // Store that ID in MASTER_ACCOUNT_ID
                    MASTER_ACCOUNT_ID = int.Parse(sr.ReadToEnd());
                }
            }
            else
            {
                MessageBox.Show("A required file did not load correctly. Please contact the IT department immediatley. CODE RED!\nThe MASTER_ACCOUNT_ID could not be loaded. \"File Not Found!\"\n\nSystem Closing...");
                bCloseNormally = false;
                this.Close();
            }

            // Update the ID display.
            lblAccountNumber.Text = "Next Account Number: " + MASTER_ACCOUNT_ID.ToString();

            // Read and Load the Account List
            if (File.Exists(accountFileLocation))
            {
                DialogResult dr = MessageBox.Show("Load all accounts?", "Load Account File?", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation);
                if (dr == DialogResult.Yes)
                {
                    RDUtil.DeserializeList<BankAccount>(accountFileLocation, ref accountList);
                }
            }
            UpdateAccountDisplay();

        }
        /// <summary>
        /// Just experimenting with override. No reason to call this
        /// </summary>
        protected override void OnFormClosing(FormClosingEventArgs e)
        {
            if (bCloseNormally)
            {
                base.OnFormClosing(e);
            }
            else
            {
                //Write some Log File about the missing file and some time sensitive hoop-de-doo
            }
        }
        protected void Form1_FormClosing(object sender, FormClosingEventArgs e)
        {
            DialogResult dr = MessageBox.Show("Save all accounts?", "Always Save Before Exit", MessageBoxButtons.YesNo, MessageBoxIcon.Exclamation);
            if (dr == DialogResult.Yes)
            {
                RDUtil.SerializeListData(accountFileLocation, accountList);
            }
            using (StreamWriter sw = new StreamWriter(Master_Account_ID_Location))
            {
                sw.WriteLine(MASTER_ACCOUNT_ID.ToString());
            }
        }

        /// <summary> Updates the ListViewItems to reflect thier currently stored values.
        /// Should be used after changing any account balances, and when reading accounts from account file.
        /// </summary>
        private void UpdateAccountDisplay()
        {
            lsvAccount.Items.Clear();
            ListViewItem lvi;
            foreach (BankAccount a in accountList)
            {
                lvi = new ListViewItem(a.GetType().Name);
                lvi.SubItems.Add(a.AccountNumber);
                lvi.SubItems.Add(a.Owner[0].FirstName);
                lvi.SubItems.Add(a.Owner[0].LastName);
                lvi.SubItems.Add(a.DateCreated.ToShortDateString());
                lvi.SubItems.Add(a.Balance.ToString("c"));
                lvi.SubItems.Add(a.Owner[0].PhoneNumber);
                lvi.SubItems.Add(a.Owner[0].Email);

                lsvAccount.Items.Add(lvi);
            }
        }

        /// <summary> Populates the Transactions ListView with the with BankAccount.
        /// </summary>
        /// <param name="account">The Account whose information you wish to display.</param>
        private void DisplayAccountTransactions(BankAccount account)
        {
            lsvTransaction.Items.Clear();
            ListViewItem lvi = null;
            foreach (Transaction t in account.TransactionList)
            {
                string amount = t.Amount.ToString("c");
                if (t.Amount < 0)
                {
                    amount = "-" + t.Amount.ToString("c");
                }
                lvi = new ListViewItem(amount);
                lvi.SubItems.Add(t.TransactionDate.ToShortDateString());
                lvi.SubItems.Add(t.TransactionType.ToString());

                lsvTransaction.Items.Add(lvi);
            }

        }

        /// <summary> Returns the selected account from the Accounts ListView. Returns null if nothing is selected.
        /// </summary>
        /// <returns></returns>
        private BankAccount GetSelectedAccount()
        {
            if (lsvAccount.SelectedItems.Count > 0)
            {
                // get selected account
                string accountNumber = lsvAccount.SelectedItems[0].SubItems[1].Text;
                BankAccount ba = GetAccountByNumber(accountNumber);
                return ba;
            }
            return null;
        }

        /// <summary> Finds account given account in the accountList
        /// </summary>
        /// <param name="accountNumber">The Account number which belongs to the Account you wish to get.</param>
        /// <returns></returns>
        private BankAccount GetAccountByNumber(string accountNumber)
        {
            foreach (BankAccount a in accountList)
            {
                if (a.AccountNumber == accountNumber)
                {
                    return a;
                }
            }
            return null;
        }



        /// <summary> Returns true if the specified BankAccount has enough funds to withdraw from.
        /// </summary>
        /// <param name="ba">The Account you wish to withdraw from.</param>
        /// <param name="amount">The dollar amount you wish to withdraw.</param>
        private void ProcessWithdraw(BankAccount ba, decimal amount)
        {
            if (ba.Withdraw(amount))
            {
                toolTip.Show("Success", btnWithdrawOrDeposit, 1300);
            }
            else
                MessageBox.Show("The account you are trying to access does not have sufficient funds.\nAccount: " + ba.AccountNumber + "\nBalance: " + ba.Balance + "\nAttempted Withdrawl: " + amount.ToString("c"));
        }

        /// <summary> Calls the Deposit(decimal amount) method of the provided BankAccount.
        /// </summary>
        /// <param name="bankAccount">The Account you wish to deposit into.</param>
        /// <param name="amount">The full amount which will be deposited.</param>
        private void ProcessDeposit(BankAccount bankAccount, decimal amount)
        {
            bankAccount.Deposit(amount);
        }

        /// EVENTS:

        // Fires when an account is selected from the Account ListView
        private void lsvAccount_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (lsvAccount.SelectedItems.Count > 0)
            {
                // set globally available selected account:
                selectedAccountIndex = lsvAccount.SelectedIndices[0];

                string accountNumber = lsvAccount.SelectedItems[0].SubItems[1].Text;

                foreach (BankAccount a in accountList)
                {
                    if (a.AccountNumber == accountNumber)
                    {
                        DisplayAccountTransactions(a);
                        break;
                    }
                }
            }
        }
        // Fires when account Deposit or Withdraw radio button is selected.
        private void radDepositAndWithdraw_CheckedChanged(object sender, EventArgs e)
        {
            if (radDeposit.Checked == true)
            {
                lblChangeOnWithdrawDeposit.Text = "Deposit Amount:";
                btnWithdrawOrDeposit.Text = "Deposit";
            }
            else if (radWithdraw.Checked == true)
            {
                lblChangeOnWithdrawDeposit.Text = "Withdraw Amount:";
                btnWithdrawOrDeposit.Text = "Withdraw";

            }
        }

        // Buttons for transfer and withdraw/deposit
        private void btnTransfer_Click(object sender, EventArgs e)
        {
            // get account numbers from user
            if (txtTransferAccountOne.Text != String.Empty && txtTransferAccountTwo.Text != String.Empty)
            {
                string acNum1 = txtTransferAccountOne.Text;
                string acNum2 = txtTransferAccountTwo.Text;
                // get account1 by number
                if (acNum1 != acNum2)
                {
                    BankAccount ba1 = GetAccountByNumber(acNum1);
                    if (ba1 != null)
                    {
                        // get account2 by number
                        BankAccount ba2 = GetAccountByNumber(acNum2);
                        if (ba2 != null)
                        {
                            // read amount
                            decimal amount;
                            if (decimal.TryParse(txtTransferAmount.Text, out amount))
                            {
                                // complete Transfer
                                if (BankAccount.TransferFunds(ba1, ba2, amount))
                                {
                                    UpdateAccountDisplay();
                                    MessageBox.Show("Transfer Complete.", "Success");
                                    txtTransferAccountOne.Clear();
                                    txtTransferAccountTwo.Clear();
                                    txtTransferAmount.Clear();
                                }
                                else
                                {
                                    MessageBox.Show("The Transfer Attempt failed. Account, " + ba1.AccountNumber + " contains insufficient funds.\n\n" +
                                                    "Current Funds: " + ba1.Balance.ToString("C") +
                                                    "\nTransfer Attempt: " + amount.ToString("C"), "Failed to Transfer");
                                }
                            }
                        }
                        else
                        {
                            toolTip.Show("Invalid Account number", txtTransferAccountTwo, 1800);
                        }
                    }
                    else
                    {
                        toolTip.Show("Invalid Account number", txtTransferAccountOne, 1800);
                    }
                }
                else
                {
                    toolTip.Show("Enter Valid Account Numbers", btnTransfer, 1800);
                }
            }
        }
        private void btnWithdrawOrDeposit_Click(object sender, EventArgs e)
        {
            // read selected bank account
            BankAccount ba = GetSelectedAccount();
            if (ba != null)
            {
                decimal amount;
                if (decimal.TryParse(txtWithdrawOrDepsoit.Text, out amount))
                {
                    // Withdraw or Deposit - radio button option
                    if (radDeposit.Checked == true)
                    {
                        // Calls the Deposit method for the selected bank account
                        ProcessDeposit(ba, amount);

                        UpdateAccountDisplay();
                        txtWithdrawOrDepsoit.Clear();

                        lsvAccount.Select();
                        lsvAccount.Items[selectedAccountIndex].Selected = true;
                    }
                    else if (radWithdraw.Checked == true)
                    {
                        ProcessWithdraw(ba, amount);

                        UpdateAccountDisplay();
                        txtWithdrawOrDepsoit.Clear();

                        lsvAccount.Select();
                        lsvAccount.Items[selectedAccountIndex].Selected = true;
                    }
                    else
                    {
                        toolTip.Show("Select Deposit or Withdraw to continue.", btnWithdrawOrDeposit, 1800);
                    }

                }
                else
                {
                    toolTip.Show("Please enter a valid doller amount\nEx: 1500.99", txtWithdrawOrDepsoit, 1800);
                }
            }
            else
            {
                toolTip.Show("Please select an account from the list", btnWithdrawOrDeposit, 1800);
            }
        }
        // Create an account button
        private void btnCreateAccount_Click(object sender, EventArgs e)
        {
            // Prepare it for use in adding accounts method...

            // get f+l name, phone, email, and amount of initial deposit
            string firstName = txtFirstName.Text;
            string lastName = txtLastName.Text;
            string phoneNo = txtPhone.Text;
            string email = txtEmail.Text;
            decimal amount;

            // create an owner
            if (firstName != String.Empty && lastName != String.Empty &&  phoneNo != String.Empty && email != String.Empty)
            {
                BankersLibrary.Owner owner = new Owner(firstName, lastName, phoneNo, email);
                // get inital deposit, and next account number (gloabl var read from text file)
                if (decimal.TryParse(txtInitialBalance.Text, out amount))
                {
                    // Determine Account Type
                    if (radChecking.Checked == true)
                    {
                        if (amount >= 500)
                        {
                            // add new account to accountList
                            CheckingAccount ca = new CheckingAccount(MASTER_ACCOUNT_ID.ToString(), amount, DateTime.Now, owner);
                            accountList.Add(ca);
                            ClearTextData_OnAddAccount();
                            UpdateAccountDisplay();
                            IncrementMasterAccountNumber();
                        }
                        else
                            MessageBox.Show("Can not createa a Checking Account with out an initial deposit of at least: $500");
                    }
                    else if (radSavings.Checked == true)
                    {
                        if (amount >= 1)
                        {
                            // add new account to accountList
                            SavingsAccount sa = new SavingsAccount(MASTER_ACCOUNT_ID.ToString(), amount, DateTime.Now, owner);
                            accountList.Add(sa);
                            ClearTextData_OnAddAccount();
                            UpdateAccountDisplay();
                            IncrementMasterAccountNumber();
                        }
                        else
                            MessageBox.Show("Can not create a Savings Account with out an initial deposit of at least: $1");
                    }
                    else
                        toolTip.Show("Select an option.", radChecking, 1800);
                }
            }
        }
        // related methods to run after creating an account
        private void IncrementMasterAccountNumber()
        {
            MASTER_ACCOUNT_ID++;
            lblAccountNumber.Text = "Next Account Number: " + MASTER_ACCOUNT_ID.ToString();
        }
        private void ClearTextData_OnAddAccount()
        {
            txtFirstName.Clear();
            txtLastName.Clear();
            txtInitialBalance.Clear();
            txtPhone.Clear();


            txtEmail.Clear();
        }

        private void txtTransferAccountOne_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (lsvAccount.SelectedItems.Count > 0)
            {
                txtTransferAccountOne.Text = lsvAccount.SelectedItems[0].SubItems[1].Text;
            }
        }

        private void txtTransferAccountTwo_MouseDoubleClick(object sender, MouseEventArgs e)
        {
            if (lsvAccount.SelectedItems.Count > 0)
            {
                txtTransferAccountTwo.Text = lsvAccount.SelectedItems[0].SubItems[1].Text;
            }
        }
    }
}
// New Lab 10/30/14 --- DUE: Tuesday, November 7th (11/7/14)
// Create account new project - BankAccount_Lab
// Add another project (Class Library) to the solution. Name it something like BankersLibrary
//
// Within BankersLibrary:
// Define an enum: TransactionType (Deposit, Withdraw, Trasfer)
// Define account class Owner. An Owner has: _first and _last name fields, _phoneNumber and _email  
// Define account class Transaction. A Transaction has: fields _amount, _transactionDate, _transactions (of type: List<Transaction>)
// Define an abstract class, BankAcount. A BankAccount has: _accountNumber, _balance, _dateCreated, _owner (of type: List<Owner>)
//             Add constructor and properties
//             Add instance methods: virtual Deposit, abstract Withdraw, Transfer, and AddOwner(Owner owner)
//             Add static methods: static Transfer
//
// Define account class: CheckingAccount, that inherits from BankAccount
// add fields: _minBalance
// Define its constructor and properties, and implement necessary methods
//
// Define account class: SavingsAccount, that also inherts from BankAccount
// Add fields: _interestRate
// Define its constructor, properties and methods.
//
// HINT: The transaction objects should be created and added within the methods
//              Deposit, Withdraw, and Transfer, because account transaction occurs when any of those 3 actions occurs.
//
// In Form1: Create account list of accounts
//              add account list view to display all the account data (Account Number, balance, creation date, owner first and last name, phone, and email)
//              when you select an Account from the listview, an even should trigger that display its transaction history in account second list view.
//
// Add UI to perform the following:
// Be able to:
//              Deposit money into account selected account
//              Withdraw money from account selected account
//              Transfer from one account to another
//
//              Provide account way to save all accounts to account file and read them back.

No comments:

Post a Comment