//ATM Simulation Implementation - Individual Transactions

ATM Simulation Implementation - Individual Transactions

/*
 * Example ATM simulation - file transaction.cc
 *
 * This file implements the classes that represent the various kinds of
 * transactions that the ATM can perform, declared in transaction.h
 *
 * Copyright (c) 1996 - Russell C. Bjork
 *
 */

#include 
#include "sysdep.h"
#include "bank.h"
#include "session.h"
#include "transaction.h"
#include "atm.h"

//


Transaction::Transaction(Session & session)
  : _session(session),
    _serialNumber(++ _lastSerialNumberAssigned)
  { }

//


int Transaction::_lastSerialNumberAssigned = 0;

//


Transaction * Transaction::makeTransaction(TransactionType type,
					   Session & session)
  {
    switch (type)
      {
	case WITHDRAWL: return new WithdrawlTransaction(session);
	case DEPOSIT:   return new DepositTransaction(session);
	case TRANSFER:  return new TransferTransaction(session);
	case INQUIRY:   return new InquiryTransaction(session);
      }
  }

//


void Transaction::doTransactionUseCase()
  {
    if (! getTransactionSpecificsFromCustomer())
	return;
    Bank::ApprovalCode code = sendToBank();
    if (code == Bank::INVALID_PIN)
	code = _session.doInvalidPINExtension();
    if (code == Bank::APPROVED)
	finishApprovedTransaction();
    else if (code != Bank::INVALID_PIN)
	theATM.reportRejection(theBank.rejectionDescription(code));
  }

//


// getTransactionSpecificsFromCustomer() is abstract for class Transaction::

bool WithdrawlTransaction::getTransactionSpecificsFromCustomer()
  {
    _fromAccount = theATM.getAccountChoice("withdraw from");
    _amount = theATM.getWithdrawlAmountChoice();
    return theATM.checkIfCashAvailable(_amount);
  }


bool DepositTransaction::getTransactionSpecificsFromCustomer()
  {
    _toAccount = theATM.getAccountChoice("deposit to");
    _amount = theATM.getAmountEntry();
    return true;
  }

bool TransferTransaction::getTransactionSpecificsFromCustomer()
  {
    _fromAccount = theATM.getAccountChoice("transfer from");
    _toAccount = theATM.getAccountChoice("transfer to");
    _amount = theATM.getAmountEntry();
    return true;
  }

bool InquiryTransaction::getTransactionSpecificsFromCustomer()
  {
    _fromAccount = theATM.getAccountChoice("balance for");
    return true;
  }

//


// sendToBank() is abstract for class Transaction::

Bank::ApprovalCode WithdrawlTransaction::sendToBank()
  {
    return theBank.initiateWithdrawl(_session.cardNumber(),
				     _session.PIN(),
				     theATM.number(),
				     _serialNumber,
				     _fromAccount,
				     _amount,
				     _newBalance,
				     _availableBalance);
  }


Bank::ApprovalCode DepositTransaction::sendToBank()
  {
    return theBank.initiateDeposit(_session.cardNumber(),
				   _session.PIN(),
				   theATM.number(),
				   _serialNumber,
				   _toAccount,
				   _amount,
				   _newBalance,
				   _availableBalance);
  }


Bank::ApprovalCode TransferTransaction::sendToBank()
  {
    return theBank.doTransfer(_session.cardNumber(),
			      _session.PIN(),
			      theATM.number(),
			      _serialNumber,
			      _fromAccount,
			      _toAccount,
			      _amount,
			      _newBalance,
			      _availableBalance);
  }


Bank::ApprovalCode InquiryTransaction::sendToBank()
  {
    return theBank.doInquiry(_session.cardNumber(),
			     _session.PIN(),
			     theATM.number(),
			     _serialNumber,
			     _fromAccount,
			     _newBalance,
			     _availableBalance);
  }

//


// finishApprovedTransaction() is abstract in class Transaction::

void WithdrawlTransaction::finishApprovedTransaction()
  {
    theATM.dispenseCash(_amount);
    theBank.finishWithdrawl(theATM.number(), _serialNumber, true);
    char description[26];
    sprintf(description, "WITHDRAWL FROM %s",theBank.accountName(_fromAccount));
    theATM.issueReceipt(_session.cardNumber(),
			_serialNumber, 
			description,
			_amount,
			_newBalance,
			_availableBalance);
  }

void DepositTransaction::finishApprovedTransaction()
  {
    bool envelopeAccepted = theATM.acceptEnvelope();
    if (envelopeAccepted)
      {
	char description[26];
	sprintf(description, "DEPOSIT TO %s", theBank.accountName(_toAccount));
	theATM.issueReceipt(_session.cardNumber(),
			    _serialNumber,
			    description,			
			    _amount,
			    _newBalance,
			    _availableBalance);
      }
    theBank.finishDeposit(theATM.number(), _serialNumber, envelopeAccepted);
  }


void TransferTransaction::finishApprovedTransaction()
  {
    char description[26];
    sprintf(description,"TRANSFER %s TO %s",theBank.accountName(_fromAccount),
					    theBank.accountName(_toAccount));
    theATM.issueReceipt(_session.cardNumber(),
			_serialNumber,
			description,
			_amount,
			_newBalance,
			_availableBalance);
  }

void InquiryTransaction::finishApprovedTransaction()
  {
    char description[26];
    sprintf(description, "INQUIRY FROM %s", theBank.accountName(_fromAccount));
    theATM.issueReceipt(_session.cardNumber(),
			_serialNumber,
			description,
			0,		// will cause this line to be omitted
			_newBalance,
			_availableBalance);
  }

//


WithdrawlTransaction::WithdrawlTransaction(Session & session)
  : Transaction(session)
  { } 

//


DepositTransaction::DepositTransaction(Session & session)
  : Transaction(session)
  { }

//


TransferTransaction::TransferTransaction(Session & session)
  : Transaction(session)

  { }

//


InquiryTransaction::InquiryTransaction(Session & session)
  : Transaction(session)

  { }

//