Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
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
38 changes: 33 additions & 5 deletions src/Lecture4_interfaces_abstract_classes/BaseTransaction.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,13 @@

import java.util.Calendar;

public abstract class BaseTransaction implements TransactionInterface {
/**
* Concrete class that implements the TransactionInterface.
* This class provides a base implementation for all transaction types.
* Subclasses (DepositTransaction, WithdrawalTransaction) override the apply() method
* to provide specific transaction behavior (polymorphism via late binding).
*/
public class BaseTransaction implements TransactionInterface {
private final int amount;
private final Calendar date;
private final String transactionID;
Expand All @@ -26,7 +32,7 @@ public BaseTransaction(int amount, @NotNull Calendar date) {

/**
* getAmount()
* @return integer
* @return double - the transaction amount
*/
public double getAmount() {
return amount; // Because we are dealing with Value types we need not worry about what we return
Expand All @@ -45,7 +51,29 @@ public Calendar getDate() {
public String getTransactionID(){
return transactionID;
}
// Method to print a transaction receipt or details
public abstract void printTransactionDetails();
public abstract void apply(BankAccount ba);

/**
* printTransactionDetails()
* Prints out the details of this transaction including the amount, date, and transaction ID.
*/
public void printTransactionDetails(){
System.out.println("Transaction Details:");
System.out.println("Transaction ID: \t" + transactionID);
System.out.println("Transaction Amount: \t" + amount);
System.out.println("Transaction Date: \t" + date.getTime());
}

/**
* apply(BankAccount ba)
* Base implementation of apply - simply prints the transaction details.
* This differs from DepositTransaction (which adds to balance) and
* WithdrawalTransaction (which subtracts from balance).
* Subclasses override this method to provide specific behavior (late binding).
* @param ba the BankAccount object to apply the transaction on
*/
public void apply(BankAccount ba) throws InsufficientFundsException {
System.out.println("Base Transaction Applied:");
printTransactionDetails();
System.out.println("Current Balance After Base Apply: \t" + ba.getBalance());
}
}
21 changes: 19 additions & 2 deletions src/Lecture4_interfaces_abstract_classes/DepositTrasaction.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@

import java.util.Calendar;

/**
* DepositTransaction extends BaseTransaction.
* Deposits are irreversible - once applied, they cannot be undone.
* Overrides the apply() method to add the deposit amount to the bank account balance.
*/
public class DepositTrasaction extends BaseTransaction {
public DepositTrasaction(int amount, @NotNull Calendar date){
super(amount, date);
Expand All @@ -19,12 +24,24 @@ private boolean checkDepositAmount(int amt){

// Method to print a transaction receipt or details
public void printTransactionDetails(){
System.out.println("Deposit Trasaction: "+this.toString());
System.out.println("Deposit Transaction: " + this.toString());
System.out.println("Amount Deposited: \t" + getAmount());
System.out.println("Transaction Date: \t" + getDate().getTime());
System.out.println("Transaction ID: \t" + getTransactionID());
}

public void apply(BankAccount ba){
/**
* apply(BankAccount ba)
* Overrides BaseTransaction.apply() to add the deposit amount to the account balance.
* This implementation differs from BaseTransaction (which only prints details) and
* WithdrawalTransaction (which subtracts from balance).
* @param ba the BankAccount object to apply the deposit on
*/
@Override
public void apply(BankAccount ba) throws InsufficientFundsException {
double curr_balance = ba.getBalance();
double new_balance = curr_balance + getAmount();
ba.setBalance(new_balance);
System.out.println("Deposit Applied Successfully. New Balance: " + ba.getBalance());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
package Lecture4_interfaces_abstract_classes;

/**
* Custom Exception class to handle insufficient funds during withdrawal transactions.
* Extends Exception to make it a checked exception, enforcing proper error handling.
*/
public class InsufficientFundsException extends Exception {

private final double amount;
private final double balance;

/**
* Constructor for InsufficientFundsException
* @param amount the withdrawal amount that was attempted
* @param balance the current balance in the account
*/
public InsufficientFundsException(double amount, double balance) {
super("Insufficient Funds: Attempted to withdraw " + amount + " but only " + balance + " available.");
this.amount = amount;
this.balance = balance;
}

/**
* getAmount()
* @return the amount that was attempted to be withdrawn
*/
public double getAmount() {
return amount;
}

/**
* getBalance()
* @return the balance at the time of the failed transaction
*/
public double getBalance() {
return balance;
}
}
114 changes: 103 additions & 11 deletions src/Lecture4_interfaces_abstract_classes/WithdrawalTransaction.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,42 +4,134 @@

import java.util.Calendar;

/**
* WithdrawalTransaction extends BaseTransaction.
* Withdrawals can be reversed - the reverse() method restores the bank account balance.
* Overrides the apply() method to subtract the withdrawal amount from the bank account balance.
* Implements exception handling for insufficient funds.
*/
public class WithdrawalTransaction extends BaseTransaction {

private double amountNotWithdrawn; // Keeps a record of the amount not withdrawn
private boolean applied; // Tracks whether this transaction has been applied
private BankAccount targetAccount; // Reference to the account the transaction was applied on

public WithdrawalTransaction(int amount, @NotNull Calendar date) {
super(amount, date);
this.amountNotWithdrawn = 0;
this.applied = false;
this.targetAccount = null;
}

private boolean checkDepositAmount(int amt) {
private boolean checkWithdrawalAmount(int amt) {
if (amt < 0) {
return false;
} else {
return true;
}
}

// Method to reverse the transaction
/**
* reverse()
* Reverses the withdrawal transaction by restoring the balance to the bank account.
* Only succeeds if the transaction was previously applied.
* @return true if reversal was successful, false otherwise
*/
public boolean reverse() {
if (!applied || targetAccount == null) {
System.out.println("Withdrawal Transaction has not been applied yet. Cannot reverse.");
return false;
}

// Restore the withdrawn amount (which is getAmount() - amountNotWithdrawn)
double withdrawnAmount = getAmount() - amountNotWithdrawn;
double currentBalance = targetAccount.getBalance();
targetAccount.setBalance(currentBalance + withdrawnAmount);
System.out.println("Withdrawal Reversed Successfully. New Balance: " + targetAccount.getBalance());
applied = false;
return true;
} // return true if reversal was successful
}

// Method to print a transaction receipt or details
public void printTransactionDetails() {
System.out.println("Deposit Trasaction: " + this.toString());
System.out.println("Withdrawal Transaction: " + this.toString());
System.out.println("Amount Withdrawn: \t" + getAmount());
System.out.println("Transaction Date: \t" + getDate().getTime());
System.out.println("Transaction ID: \t" + getTransactionID());
if (amountNotWithdrawn > 0) {
System.out.println("Amount Not Withdrawn: \t" + amountNotWithdrawn);
}
}

/**
* apply(BankAccount ba)
* Overrides BaseTransaction.apply() to subtract the withdrawal amount from the account balance.
* Uses the throws keyword to handle InsufficientFundsException when the balance
* is less than the withdrawal amount.
* @param ba the BankAccount object to apply the withdrawal on
* @throws InsufficientFundsException if the balance is less than the withdrawal amount
*/
@Override
public void apply(BankAccount ba) throws InsufficientFundsException {
double curr_balance = ba.getBalance();
if (curr_balance < getAmount()) {
throw new InsufficientFundsException(getAmount(), curr_balance);
}
double new_balance = curr_balance - getAmount();
ba.setBalance(new_balance);
this.applied = true;
this.targetAccount = ba;
System.out.println("Withdrawal Applied Successfully. New Balance: " + ba.getBalance());
}

/*
Oportunity for assignment: implementing different form of withdrawal
/**
* Overloaded apply() method (Q3)
* Not only checks if the balance covers the withdrawal amount but also checks
* if the balance is greater than 0. In the case when 0 < balance < withdrawal amount,
* it withdraws all the balance and keeps a record of the amount not withdrawn.
* Implements exception handling using try{...} catch{...} finally{...} block.
* @param ba the BankAccount object to apply the withdrawal on
* @param checkAvailableBalance flag to indicate that this overloaded version should be used
*/
public void apply(BankAccount ba) {
public void apply(BankAccount ba, boolean checkAvailableBalance) {
double curr_balance = ba.getBalance();
if (curr_balance > getAmount()) {

try {
// Check if the balance covers the withdrawal amount
if (curr_balance < getAmount()) {
throw new InsufficientFundsException(getAmount(), curr_balance);
}

// Sufficient funds - withdraw the full amount
double new_balance = curr_balance - getAmount();
ba.setBalance(new_balance);
this.amountNotWithdrawn = 0;
System.out.println("Withdrawal Applied Successfully. New Balance: " + ba.getBalance());

} catch (InsufficientFundsException e) {
// If the balance is greater than 0 but less than the withdrawal amount
// Withdraw all the available balance and keep a record of the amount not withdrawn
if (curr_balance > 0) {
this.amountNotWithdrawn = getAmount() - curr_balance;
ba.setBalance(0);
System.out.println("Partial Withdrawal: Only " + curr_balance + " was available.");
System.out.println("Amount Not Withdrawn: " + amountNotWithdrawn);
} else {
this.amountNotWithdrawn = getAmount();
System.out.println("Error: " + e.getMessage());
}
} finally {
this.applied = true;
this.targetAccount = ba;
System.out.println("Transaction Complete. Final Balance: " + ba.getBalance());
}
}

/*
Assignment 1 Q3: Write the Reverse method - a method unique to the WithdrawalTransaction Class
/**
* getAmountNotWithdrawn()
* @return the amount that could not be withdrawn due to insufficient funds
*/
public double getAmountNotWithdrawn() {
return amountNotWithdrawn;
}
}

Loading