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
14 changes: 12 additions & 2 deletions src/Lecture4_interfaces_abstract_classes/BaseTransaction.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ public BaseTransaction(int amount, @NotNull Calendar date) {
* getAmount()
* @return integer
*/

public double getAmount() {
return amount; // Because we are dealing with Value types we need not worry about what we return
}
Expand All @@ -36,16 +37,25 @@ public double getAmount() {
* getDate()
* @return Calendar Object
*/

public Calendar getDate() {
// return date; // Because we are dealing with Reference types we need to judiciously copy what our getters return
return (Calendar) date.clone(); // Defensive copying or Judicious Copying
}

// Method to get a unique identifier for the transaction

public String getTransactionID(){
return transactionID;
}
// Method to print a transaction receipt or details
public abstract void printTransactionDetails();
public abstract void apply(BankAccount ba);

public void printTransactionDetails() {
System.out.println("Transaction ID: " + transactionID + "|Amount: $" + amount);
}
public void apply(BankAccount ba) throws InsufficientFundsException
//using this since it is a base implementation it does not know whether it is adding or removing money.
{
System.out.println("Applying a standard base transaction record");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

import java.util.Calendar;

public class DepositTrasaction extends BaseTransaction {
public DepositTrasaction(int amount, @NotNull Calendar date){
public class DepositTransaction extends BaseTransaction {
public DepositTransaction(int amount, @NotNull Calendar date){
super(amount, date);
}
private boolean checkDepositAmount(int amt){
Expand All @@ -18,11 +18,13 @@ private boolean checkDepositAmount(int amt){
}

// Method to print a transaction receipt or details
public void printTransactionDetails(){
System.out.println("Deposit Trasaction: "+this.toString());
@Override
public void printTransactionDetails() {
System.out.println("Deposit Transaction: "+this.toString());
}

public void apply(BankAccount ba){
@Override
public void apply(BankAccount ba) throws InsufficientFundsException {
double curr_balance = ba.getBalance();
double new_balance = curr_balance + getAmount();
ba.setBalance(new_balance);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package Lecture4_interfaces_abstract_classes;

public class InsufficientFundsException extends Exception {
public InsufficientFundsException(String message) {
super(message);
}
}
153 changes: 153 additions & 0 deletions src/Lecture4_interfaces_abstract_classes/TransactionGui.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
package Lecture4_interfaces_abstract_classes;

import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.util.Calendar;
import java.text.SimpleDateFormat;

/**
* An advanced graphical user interface class that extends JFrame.
* Displays real-time bank account variables, current balances, and full transaction logs.
*/
public class TransactionGui extends JFrame {
private BankAccount account;
private JTextField amountField;
private JLabel balanceLabel;
private JLabel statusLabel;

// UI elements to display the complete transaction history
private DefaultTableModel tableModel;
private JTable historyTable;
private SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

public TransactionGui() {
// Start the simulator account with $1000
account = new BankAccount(1000.0);

// Frame Setup
setTitle("Interactive Bank Account Ledger Dashboard");
setSize(650, 500);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout(15, 15));

// 1. TOP PANEL: Real-time Account Metrics Visualization
JPanel headerPanel = new JPanel(new GridLayout(2, 1));
headerPanel.setBackground(new Color(40, 50, 70));
headerPanel.setBorder(BorderFactory.createEmptyBorder(10, 15, 10, 15));

balanceLabel = new JLabel("Live Account Balance: $" + account.getBalance());
balanceLabel.setFont(new Font("SansSerif", Font.BOLD, 22));
balanceLabel.setForeground(Color.WHITE);

statusLabel = new JLabel("System Status: Operational | Standing: Good");
statusLabel.setFont(new Font("SansSerif", Font.PLAIN, 13));
statusLabel.setForeground(new Color(150, 230, 150)); // Gentle green

headerPanel.add(balanceLabel);
headerPanel.add(statusLabel);
add(headerPanel, BorderLayout.NORTH);

// 2. CENTER PANEL: Detailed Transaction History Table
String[] columnNames = {"Type", "Transaction ID", "Timestamp", "Amount Changed", "Final Balance"};
tableModel = new DefaultTableModel(columnNames, 0);
historyTable = new JTable(tableModel);
historyTable.setFont(new Font("Monospaced", Font.PLAIN, 12));
historyTable.setRowHeight(22);

JScrollPane tableScrollPane = new JScrollPane(historyTable);
tableScrollPane.setBorder(BorderFactory.createTitledBorder("Complete Invariant Audit Trail Ledger"));
add(tableScrollPane, BorderLayout.CENTER);

// 3. SOUTH PANEL: User Interaction Controls & Inputs
JPanel controlPanel = new JPanel(new BorderLayout(10, 10));
controlPanel.setBorder(BorderFactory.createEmptyBorder(10, 15, 15, 15));

// Input row
JPanel inputRow = new JPanel(new FlowLayout(FlowLayout.CENTER, 10, 5));
JLabel amountLabel = new JLabel("Enter Amount ($):");
amountLabel.setFont(new Font("SansSerif", Font.BOLD, 14));
amountField = new JTextField(10);
amountField.setFont(new Font("SansSerif", Font.PLAIN, 14));

inputRow.add(amountLabel);
inputRow.add(amountField);
controlPanel.add(inputRow, BorderLayout.NORTH);

// Buttons row
JPanel buttonRow = new JPanel(new GridLayout(1, 2, 15, 0));
JButton depositBtn = new JButton("Execute Deposit (+)");
depositBtn.setBackground(new Color(220, 245, 220));
depositBtn.setFont(new Font("SansSerif", Font.BOLD, 13));

JButton withdrawBtn = new JButton("Execute Withdrawal (-)");
withdrawBtn.setBackground(new Color(255, 220, 220));
withdrawBtn.setFont(new Font("SansSerif", Font.BOLD, 13));

buttonRow.add(depositBtn);
buttonRow.add(withdrawBtn);
controlPanel.add(buttonRow, BorderLayout.SOUTH);

add(controlPanel, BorderLayout.SOUTH);

// Event Action Hook Handlers
depositBtn.addActionListener(e -> processUiTransaction("Deposit"));
withdrawBtn.addActionListener(e -> processUiTransaction("Withdrawal"));

setLocationRelativeTo(null); // Open in center of monitor display
}

private void processUiTransaction(String type) {
// Reset status message color layout labels
statusLabel.setForeground(new Color(150, 230, 150));
statusLabel.setText("System Status: Processing...");

try {
int amount = Integer.parseInt(amountField.getText().trim());
Calendar timestamp = Calendar.getInstance();
String timeString = dateFormat.format(timestamp.getTime());

if (type.equals("Deposit")) {
DepositTransaction dt = new DepositTransaction(amount, timestamp);
dt.apply(account); // Core OOP math call

// Add complete transaction info array directly onto the GUI viewport rows!
tableModel.addRow(new Object[]{
"DEPOSIT", dt.getTransactionID(), timeString, "+$" + amount, "$" + account.getBalance()
});
statusLabel.setText("System Status: Deposit Succeeded.");

} else {
WithdrawalTransaction wt = new WithdrawalTransaction(amount, timestamp);
wt.apply(account); // Core OOP math call (throws exception if insufficient)

tableModel.addRow(new Object[]{
"WITHDRAWAL", wt.getTransactionID(), timeString, "-$" + amount, "$" + account.getBalance()
});
statusLabel.setText("System Status: Withdrawal Succeeded.");
}

updateDashboardView();

} catch (NumberFormatException ex) {
statusLabel.setForeground(Color.ORANGE);
statusLabel.setText("System Status: Input Format Rejection.");
JOptionPane.showMessageDialog(this, "Please input a clean integer numeric total.", "Format Error", JOptionPane.WARNING_MESSAGE);
} catch (InsufficientFundsException ex) {
// Instantly captures and logs custom exception details straight onto the visual metrics panel
statusLabel.setForeground(new Color(255, 120, 120)); // Warning Red
statusLabel.setText("System Status: DECLINED - " + ex.getMessage());

JOptionPane.showMessageDialog(this, ex.getMessage(), "Transaction Core Exception Blocker", JOptionPane.ERROR_MESSAGE);
}
}

private void updateDashboardView() {
balanceLabel.setText("Live Account Balance: $" + account.getBalance());
amountField.setText("");
}

public static void main(String[] args) {
SwingUtilities.invokeLater(() -> new TransactionGui().setVisible(true));
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
package Lecture4_interfaces_abstract_classes;

import java.util.Calendar;

/**
Expand All @@ -16,6 +17,9 @@ public interface TransactionInterface {
// Method to get a unique identifier for the transaction
String getTransactionID();

}

// ADDED FOR QUESTION 1: Method to print a transaction receipt or details
void printTransactionDetails();

// ADDED FOR QUESTION 1 & 3: Method to apply transaction logic to an account balance
void apply(BankAccount ba) throws InsufficientFundsException;
}
68 changes: 54 additions & 14 deletions src/Lecture4_interfaces_abstract_classes/WithdrawalTransaction.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,41 +5,81 @@
import java.util.Calendar;

public class WithdrawalTransaction extends BaseTransaction {

private double amountNotWithdrawn =0;

public WithdrawalTransaction(int amount, @NotNull Calendar date) {
super(amount, date);
}

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


// Method to reverse the transaction
public boolean reverse() {
public boolean reverse(BankAccount ba) {
double curr_balance=ba.getBalance();
double restore_balance = curr_balance + getAmount();
ba.setBalance(restore_balance);
return true;
} // return true if reversal was successful

// Method to print a transaction receipt or details
@Override
public void printTransactionDetails() {
System.out.println("Deposit Trasaction: " + this.toString());
System.out.println("Withdrawal TransactionID: " + getTransactionID() + "|Amount:$ " +getAmount());
}

/*
Oportunity for assignment: implementing different form of withdrawal
Opportunity for assignment: implementing different form of withdrawal
*/
public void apply(BankAccount ba) {
@Override
public void apply(BankAccount ba) throws InsufficientFundsException {
double curr_balance = ba.getBalance();
if (curr_balance > getAmount()) {
double new_balance = curr_balance - getAmount();
ba.setBalance(new_balance);
if (ba.getBalance() < getAmount()) {

throw new InsufficientFundsException("Insufficient Funds! Transaction declined.");

}
double new_balance = curr_balance - getAmount();
ba.setBalance(new_balance);
}

/*
public void apply (BankAccount ba, boolean allowPartial) {
try {
double curr_balance = ba.getBalance();
double withdrawalAmount = getAmount();

if (curr_balance > 0 && curr_balance < withdrawalAmount) {
this.amountNotWithdrawn = withdrawalAmount - curr_balance;
ba.setBalance(0);
System.out.println("Partial withdrawal processed. Deficit remainder: $" + amountNotWithdrawn);
} else {
apply(ba);
System.out.println("Standard withdrawal successfully processed.");
}
} catch (InsufficientFundsException e) {
// Local exception catch blocks keep execution stack safe from unexpected system failure
System.err.println("Transaction Blocked locally: " + e.getMessage());

} finally {
// Mandatory block confirming transaction state evaluations are structurally over
System.out.println("Transaction pipeline process completed.");
}
}
public double getAmountNotWithdrawn() {
return amountNotWithdrawn;
}

/*
Assignment 1 Q3: Write the Reverse method - a method unique to the WithdrawalTransaction Class
*/


}





Loading