Compare commits

..

4 Commits

Author SHA1 Message Date
Derek L. Seitz 43f6c3b6f2 Upload files to "/" 2025-03-11 21:19:46 +00:00
Derek 1f14a6c13b
Update README.md
Corrected typos and added "Back to Top" links throughout document
2025-01-03 23:52:21 -06:00
Derek 6a7781de40
Update README.md
Updated table of contents to include anchor links for subheadings in Scenario and Application Architecture & Components sections
2025-01-03 23:39:28 -06:00
ds.731 a53bfef53e Phase IV
- Added BankAcctAppGUI as a GUI frontend to replace CLI
- Enhanced DataEntry to use Regex patterns for input validation
2025-01-02 16:09:30 -06:00
24 changed files with 982 additions and 102 deletions

View File

@ -7,7 +7,18 @@
- [Table of Contents](#table-of-contents)
- [Introduction](#introduction)
- [Scenario:](#scenario)
- [Application Architecture \& Components](#application-architecture--components)
- [Phase I: Creating the Initial Classes](#phase-i-creating-the-initial-classes)
- [Phase II: Adding an Abstract Superclass & Input Data Validation](#phase-ii-adding-an-abstract-superclass--input-data-validation)
- [Phase III: Adding & Implementing Subclasses](#phase-iii-adding--implementing-subclasses)
- [Phase IV: Creating the Application GUI](#phase-iv-creating-the-application-gui)
- [Application Architecture & Components](#application-architecture--components)
- [DataEntry Class](#dataentry-class)
- [Customer Class](#customer-class)
- [BankAcctApp Class](#bankacctapp-class)
- [Account Abstract Superclass](#account-abstract-superclass)
- [CheckingAccount & SavingsAccount Subclasses](#checkingaccount--savingsaccount-subclasses)
- [AccountInterface Interface](#accountinterface-interface)
- [BankAcctAppGUI Class](#bankacctappgui-class)
- [Functionality \& Rationale](#functionality--rationale)
- [Running Application Screenshots \& Demo](#running-application-screenshots--demo)
- [Potential for Scalability \& Future Enhancements](#potential-for-scalability--future-enhancements)
@ -39,6 +50,8 @@ During the first three phases, the application employs console-based input and o
- ## Phase IV: Adding a GUI Frontend
The final phase of the project, Phase IV, creates a **graphical user interface (GUI)** to replace the console interface. The GUI is created using **Swing classes** to include **JFrames**, **JPanels**, and other GUI components. This GUI uses a combination of **BorderLayout**, **GridBagLayout**, and **FlowLayout** to manage the GUI's layout design.
[Back to Top](#table-of-contents)
<br>
# Application Architecture & Components
@ -64,6 +77,7 @@ The application follows a modular design to provide clearly-defined separation o
- Shared Rules: Logic is implemented to prevent overdrafting savings accounts and to ensure no interest is applied to account balances of $0 or less.
These subclasses provide distinct account management features while adhering to shared principles of financial security and error handling.
- ## AccountInterface Interface
The **AccountInterface** serves three key purposes:
**1. Enforce encapsulation** by defining a consistent interface for interacting with account objects.
@ -73,20 +87,30 @@ The application follows a modular design to provide clearly-defined separation o
- ## BankAcctAppGUI Class
The **BankAcctAppGUI class** is responsible for implementing the **graphical user interface (GUI)** introduced in **Phase IV**. It utilizes **Java's Swing library**, incorporating **JFrame** for the main application window and **JPanel** for creating distinct sections within the interface. **FlowLayout**, **BorderLayout**, and **GridBagLayout** are implemented to position GUI components in an intuitive manner. The GUI leverages the **enhanced data validation engine** from the **DataEntry class** to ensure data integrity and security. This class facilitates user interaction with the application through a more visually appealing and user-friendly interface. More details and screenshots are provided in the [Functionality & Rationale](#functionality--rationale) and [Running Application Screenshots & Demo](#running-application-screenshots--demo) sections below.
[Back to Top](#table-of-contents)
<br>
# Functionality & Rationale
[Back to Top](#table-of-contents)
<br>
# Running Application Screenshots & Demo
[Back to Top](#table-of-contents)
<br>
# Potential for Scalability & Future Enhancements
[Back to Top](#table-of-contents)
<br>
# Project Issues & Lessons Learned
[Back to Top](#table-of-contents)

BIN
bank-account-app.jar Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -1,11 +1,11 @@
/* Phase III */
/* Phase IV */
package bankAcctApp;
import java.util.ArrayList;
// Abstract class defining the structure for account types
public abstract class Account implements AccountInterface {
// Abstract class defining the structure for account types
public abstract class Account implements AccountInterface {
private String accountNumber; // Account number for each account
private String accountType; // Type of account (CHK or SAV)
private double svcFee; // Service fee for transactions
@ -99,4 +99,4 @@ public abstract class Account implements AccountInterface {
// Abstract method for applying accrued interest
public abstract double applyAccruedInterest(String transactionDate);
}
}

View File

@ -1,4 +1,4 @@
/* Phase III */
/* Phase IV */
package bankAcctApp;

View File

@ -1,4 +1,4 @@
/* Phase III */
/* Phase IV */
package bankAcctApp;
@ -10,6 +10,7 @@ public class BankAcctApp {
ArrayList<Customer> customers = new ArrayList<>();
ArrayList<Account> accounts = new ArrayList<>();
new BankAcctAppGUI(customers, accounts);
boolean moreCustomers = true;
// Add customers and accounts

View File

@ -0,0 +1,763 @@
/* Phase IV */
package bankAcctApp;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
public class BankAcctAppGUI extends JFrame {
private JButton addCustomerBtn, addTransactionBtn, viewInfoBtn;
private ArrayList<Customer> customers;
private ArrayList<Account> accounts;
public BankAcctAppGUI(ArrayList<Customer> customers, ArrayList<Account> accounts) {
super("Bank Account Application");
this.customers = customers;
this.accounts = accounts;
setSize(800, 600);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setLayout(new BorderLayout());
JPanel mainPanel = new JPanel();
mainPanel.setLayout(new FlowLayout(FlowLayout.CENTER, 10, 10));
addCustomerBtn = new JButton("Add Customer and Account");
addCustomerBtn.setPreferredSize(new Dimension(200, 50));
addTransactionBtn = new JButton("Add Transactions to Existing Account");
addTransactionBtn.setPreferredSize(new Dimension(200, 50));
viewInfoBtn = new JButton("View Customer Account Info");
viewInfoBtn.setPreferredSize(new Dimension(200, 50));
mainPanel.add(addCustomerBtn);
mainPanel.add(addTransactionBtn);
mainPanel.add(viewInfoBtn);
JPanel centerPanel = new JPanel(new GridBagLayout());
centerPanel.add(mainPanel);
add(centerPanel, BorderLayout.CENTER);
addCustomerBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
showAddCustomerPanel();
}
});
addTransactionBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
showAddTransactionPanel();
}
});
viewInfoBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
showViewInfoPanel();
}
});
setVisible(true);
}
private void showAddCustomerPanel() {
JFrame addCustomerFrame = new JFrame("Add Customer and Account");
addCustomerFrame.setSize(800, 600);
addCustomerFrame.setLayout(new BorderLayout());
JPanel customerPanel = new JPanel(new GridBagLayout());
JPanel accountPanel = new JPanel(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(5, 5, 5, 5);
gbc.fill = GridBagConstraints.HORIZONTAL;
// Customer Information
gbc.gridx = 0;
gbc.gridy = 0;
customerPanel.add(new JLabel("Customer ID:"), gbc);
gbc.gridx = 1;
JTextField idTxtFld = new JTextField(15);
customerPanel.add(idTxtFld, gbc);
gbc.gridx = 0;
gbc.gridy = 1;
customerPanel.add(new JLabel("SSN:"), gbc);
gbc.gridx = 1;
JTextField ssnTxtFld = new JTextField(15);
customerPanel.add(ssnTxtFld, gbc);
gbc.gridx = 0;
gbc.gridy = 2;
customerPanel.add(new JLabel("Last Name:"), gbc);
gbc.gridx = 1;
JTextField lastNameTxtFld = new JTextField(15);
customerPanel.add(lastNameTxtFld, gbc);
gbc.gridx = 0;
gbc.gridy = 3;
customerPanel.add(new JLabel("First Name:"), gbc);
gbc.gridx = 1;
JTextField firstNameTxtFld = new JTextField(15);
customerPanel.add(firstNameTxtFld, gbc);
gbc.gridx = 0;
gbc.gridy = 4;
customerPanel.add(new JLabel("Street Address:"), gbc);
gbc.gridx = 1;
JTextField streetTxtFld = new JTextField(15);
customerPanel.add(streetTxtFld, gbc);
gbc.gridx = 0;
gbc.gridy = 5;
customerPanel.add(new JLabel("City:"), gbc);
gbc.gridx = 1;
JTextField cityTxtFld = new JTextField(15);
customerPanel.add(cityTxtFld, gbc);
gbc.gridx = 0;
gbc.gridy = 6;
customerPanel.add(new JLabel("State:"), gbc);
gbc.gridx = 1;
String[] states = {
"AL", "AK", "AZ", "AR", "CA", "CO", "CT", "DE", "FL", "GA",
"HI", "ID", "IL", "IN", "IA", "KS", "KY", "LA", "ME", "MD",
"MA", "MI", "MN", "MS", "MO", "MT", "NE", "NV", "NH", "NJ",
"NM", "NY", "NC", "ND", "OH", "OK", "OR", "PA", "RI", "SC",
"SD", "TN", "TX", "UT", "VT", "VA", "WA", "WV", "WI", "WY"
};
JComboBox<String> stateDropdown = new JComboBox<>(states);
customerPanel.add(stateDropdown, gbc);
gbc.gridx = 0;
gbc.gridy = 7;
customerPanel.add(new JLabel("ZIP Code:"), gbc);
gbc.gridx = 1;
JTextField zipTxtFld = new JTextField(15);
customerPanel.add(zipTxtFld, gbc);
gbc.gridx = 0;
gbc.gridy = 8;
customerPanel.add(new JLabel("Phone:"), gbc);
gbc.gridx = 1;
JTextField phoneTxtFld = new JTextField(10);
customerPanel.add(phoneTxtFld, gbc);
// Account Information
gbc.gridx = 0;
gbc.gridy = 0;
accountPanel.add(new JLabel("Account Number:"), gbc);
gbc.gridx = 1;
JTextField acctNumTxtFld = new JTextField(15);
accountPanel.add(acctNumTxtFld, gbc);
gbc.gridx = 0;
gbc.gridy = 1;
accountPanel.add(new JLabel("Account Type:"), gbc);
gbc.gridx = 1;
JRadioButton chkRadio = new JRadioButton("Checking");
JRadioButton savRadio = new JRadioButton("Savings");
ButtonGroup acctTypeGroup = new ButtonGroup();
acctTypeGroup.add(chkRadio);
acctTypeGroup.add(savRadio);
JPanel radioPanel = new JPanel(new FlowLayout(FlowLayout.LEFT));
radioPanel.add(chkRadio);
radioPanel.add(savRadio);
accountPanel.add(radioPanel, gbc);
gbc.gridx = 0;
gbc.gridy = 2;
accountPanel.add(new JLabel("Service Fee:"), gbc);
gbc.gridx = 1;
JTextField svcFeeTxtFld = new JTextField(15);
accountPanel.add(svcFeeTxtFld, gbc);
gbc.gridx = 0;
gbc.gridy = 3;
accountPanel.add(new JLabel("Interest Rate:"), gbc);
gbc.gridx = 1;
JTextField intRateTxtFld = new JTextField(15);
accountPanel.add(intRateTxtFld, gbc);
gbc.gridx = 0;
gbc.gridy = 4;
accountPanel.add(new JLabel("Overdraft Fee: "), gbc);
gbc.gridx = 1;
JTextField ovDrftTxtFld = new JTextField(15);
accountPanel.add(ovDrftTxtFld, gbc);
gbc.gridx = 0;
gbc.gridy = 5;
accountPanel.add(new JLabel("Starting Balance:"), gbc);
gbc.gridx = 1;
JTextField startBalTxtFld = new JTextField(15);
accountPanel.add(startBalTxtFld, gbc);
JPanel buttonPanel = new JPanel();
JButton saveBtn = new JButton("Save");
JButton clearBtn = new JButton("Clear");
JButton cancelBtn = new JButton("Cancel");
buttonPanel.add(saveBtn);
buttonPanel.add(clearBtn);
buttonPanel.add(cancelBtn);
addCustomerFrame.add(customerPanel, BorderLayout.NORTH);
addCustomerFrame.add(accountPanel, BorderLayout.CENTER);
addCustomerFrame.add(buttonPanel, BorderLayout.SOUTH);
addCustomerFrame.setVisible(true);
// Add action listeners for buttons
saveBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("--Action Event-- saveBtn clicked DataEntry validation engine starting.");
try {
// Create a new instance of Customer and Account at the beginning
System.out.println("Attempting to create new Customer.");
Customer customer = new Customer();
System.out.println("New Customer created.");
System.out.println("\nStarting Customer Information validation.");
// ----------------- Customer Information -----------------
System.out.println("Starting [id] validation.");
String id = idTxtFld.getText().trim();
DataEntry.inputIDGUI(id); // Use the GUI-specific validation method for ID
customer.setID(id);
System.out.println("[id] validated.");
System.out.println("Starting [ssn] validation.");
String ssn = ssnTxtFld.getText().trim();
DataEntry.inputSSNGUI(ssn); // Use the GUI-specific validation method for SSN
customer.setSSN(ssn);
System.out.println("[ssn] validated.");
System.out.println("Starting [lastName] validation.");
String lastName = lastNameTxtFld.getText().trim();
DataEntry.inputLastNameGUI(lastName); // Use the GUI-specific validation method for last name
customer.setLastName(lastName);
System.out.println("[lastName] validated.");
System.out.println("Starting [firstName] validation.");
String firstName = firstNameTxtFld.getText().trim();
DataEntry.inputFirstNameGUI(firstName); // Use the GUI-specific validation method for first name
customer.setFirstName(firstName);
System.out.println("[firstName] validated.");
System.out.println("Starting [street] validation.");
String street = streetTxtFld.getText().trim();
DataEntry.inputStreetGUI(street); // Use the GUI-specific validation method for street
customer.setStreet(street);
System.out.println("[street] validated.");
System.out.println("Starting [city] validation.");
String city = cityTxtFld.getText().trim();
DataEntry.inputCityGUI(city); // Use the GUI-specific validation method for city
customer.setCity(city);
System.out.println("[city] validated");
// Handle dropdown for State
System.out.println("Starting [state] validation.");
String state = (String) stateDropdown.getSelectedItem();
if (state == null || state.isEmpty()) {
throw new IllegalArgumentException("State must be selected.");
}
customer.setState(state);
System.out.println("[state] validated.");
System.out.println("Starting [zip] validation.");
String zip = zipTxtFld.getText().trim();
DataEntry.inputZipGUI(zip); // Use the GUI-specific validation method for zip
customer.setZip(zip);
System.out.println("[zip] validated.");
System.out.println("Starting [phone] validation.");
String phone = phoneTxtFld.getText().trim();
DataEntry.inputPhoneGUI(phone); // Use the GUI-specific validation method for phone
customer.setPhone(phone);
System.out.println("[phone] validated.");
System.out.println("Customer Information validation completed.");
// ----------------- Account Information -----------------
// Create Null account object
Account account = null;
// Determine account type
System.out.println("Checking for account type.");
System.out.println("Attempting to create new account.");
if (chkRadio.isSelected()) {
account = new CheckingAccount();
account.setAccountType("CHK");
System.out.println("Account type accepted.");
System.out.println("New Checking Account created.");
} else if (savRadio.isSelected()) {
account = new SavingsAccount();
account.setAccountType("SAV");
System.out.println("Account type accepted.");
System.out.println("New Savings Account created.");
} else {
throw new IllegalArgumentException("Account type must be selected.");
}
// Account number validation
System.out.println("Starting [accountNumber] validation.");
String accountNumber = acctNumTxtFld.getText().trim();
DataEntry.inputNumericStringGUI(accountNumber, 5); // Use GUI-specific validation method for account number
account.setAccountNumber(accountNumber); // Set account number in the account instance
System.out.println("[accountNumber] validated.");
// Service fee validation
System.out.println("Starting [svcFee] validation.");
String svcFeeStr = svcFeeTxtFld.getText().trim();
try {
double svcFee = DataEntry.inputDecimalInRangeGUI(svcFeeStr, 0.00, 10.00); // Validate and convert to double
account.setSvcFee(svcFee); // Set service fee in the same Account instance
System.out.println("[svcFee] validated.");
} catch (IllegalArgumentException ex) {
JOptionPane.showMessageDialog(addCustomerFrame, ex.getMessage(), "Input Error", JOptionPane.ERROR_MESSAGE);
return; // Prevent further processing if invalid input
}
// Interest rate validation
System.out.println("Starting [interestRate] validation.");
String intRateStr = intRateTxtFld.getText().trim();
try {
double interestRate = DataEntry.inputDecimalInRangeGUI(intRateStr, 0.0, 10.0); // Validate and convert to double
account.setInterestRate(interestRate); // Set interest rate
System.out.println("[interestRate] validated.");
} catch (IllegalArgumentException ex) {
JOptionPane.showMessageDialog(addCustomerFrame, ex.getMessage(), "Input Error", JOptionPane.ERROR_MESSAGE);
return; // Prevent further processing if invalid input
}
// Overdraft fee validation
System.out.println("Starting [overdraftFee] validation.");
String ovDrftFeeStr = ovDrftTxtFld.getText().trim();
try {
double overdraftFee = DataEntry.inputDecimalGUI(ovDrftFeeStr); // Validate and convert to double
account.setOverDraftFee(overdraftFee); // Set overdraft fee
System.out.println("[overdraftFee] validated.");
} catch (IllegalArgumentException ex) {
JOptionPane.showMessageDialog(addCustomerFrame, ex.getMessage(), "Input Error", JOptionPane.ERROR_MESSAGE);
return; // Prevent further processing if invalid input
}
// Starting balance validation
System.out.println("Starting [startingBalance] validation.");
String startBalStr = startBalTxtFld.getText().trim();
try {
double startingBalance = DataEntry.inputDecimalGUI(startBalStr); // Validate and convert to double
account.setBalance(startingBalance); // Set starting balance
System.out.println("[startingBalance] validated.");
} catch (IllegalArgumentException ex) {
JOptionPane.showMessageDialog(addCustomerFrame, ex.getMessage(), "Input Error", JOptionPane.ERROR_MESSAGE);
return; // Prevent further processing if invalid input
}
// ----------------- Add to Collections -----------------
System.out.println("Adding customer instance to customers collection.");
customers.add(customer); // Add customer to collection
System.out.println("Customer was successfully added.");
System.out.println("Adding account instance to accounts collection.");
accounts.add(account); // Add account to collection
System.out.println("Account was successfully added.");
// ----------------- Success Message -----------------
JOptionPane.showMessageDialog(addCustomerFrame, "Customer and Account added successfully!");
// ----------------- Clear Fields -----------------
System.out.println("Clearing JTextField form controls.");
idTxtFld.setText("");
ssnTxtFld.setText("");
lastNameTxtFld.setText("");
firstNameTxtFld.setText("");
streetTxtFld.setText("");
cityTxtFld.setText("");
stateDropdown.setSelectedIndex(0);
zipTxtFld.setText("");
phoneTxtFld.setText("");
acctNumTxtFld.setText("");
svcFeeTxtFld.setText("");
intRateTxtFld.setText("");
ovDrftTxtFld.setText("");
startBalTxtFld.setText("");
System.out.println("JTextField form controls cleared successfully.");
} catch (IllegalArgumentException ex) {
// Display validation error message and keep fields unchanged for correction
JOptionPane.showMessageDialog(addCustomerFrame, ex.getMessage(), "Validation Error", JOptionPane.ERROR_MESSAGE);
}
}
});
clearBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// Clear all text fields
System.out.println("--Action Event-- clearBtn clicked.");
System.out.println("Clearing JTextField form controls.");
idTxtFld.setText("");
ssnTxtFld.setText("");
lastNameTxtFld.setText("");
firstNameTxtFld.setText("");
streetTxtFld.setText("");
cityTxtFld.setText("");
stateDropdown.setSelectedIndex(0);
zipTxtFld.setText("");
acctNumTxtFld.setText("");
svcFeeTxtFld.setText("");
intRateTxtFld.setText("");
ovDrftTxtFld.setText("");
startBalTxtFld.setText("");
System.out.println("JTextField form controls cleared successfully.");
}
});
cancelBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("--Action Event-- cancelBtn Clicked -- Operation canceled.");
addCustomerFrame.dispose();
}
});
}
private void showAddTransactionPanel() {
JFrame addTransactionFrame = new JFrame("Add Transaction");
addTransactionFrame.setSize(800, 600);
addTransactionFrame.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(5, 5, 5, 5);
gbc.fill = GridBagConstraints.HORIZONTAL;
// Account Number
gbc.gridx = 0;
gbc.gridy = 0;
addTransactionFrame.add(new JLabel("Account Number:"), gbc);
gbc.gridx = 1;
JTextField acctNumTxtFld = new JTextField(15);
addTransactionFrame.add(acctNumTxtFld, gbc);
// Transaction Type (Radio Buttons for Deposit or Withdrawal)
gbc.gridx = 0;
gbc.gridy = 1;
addTransactionFrame.add(new JLabel("Transaction Type:"), gbc);
gbc.gridx = 1;
// Create the radio buttons for deposit and withdrawal types
JRadioButton depositButton = new JRadioButton("Deposit");
JRadioButton withdrawalButton = new JRadioButton("Withdrawal");
// Group the radio buttons
ButtonGroup transactionTypeGroup = new ButtonGroup();
transactionTypeGroup.add(depositButton);
transactionTypeGroup.add(withdrawalButton);
// Add the radio buttons to the panel
JPanel transactionTypePanel = new JPanel();
transactionTypePanel.add(depositButton);
transactionTypePanel.add(withdrawalButton);
addTransactionFrame.add(transactionTypePanel, gbc);
// Date (Transaction Date)
gbc.gridx = 0;
gbc.gridy = 2;
addTransactionFrame.add(new JLabel("Transaction Date (MM/dd/yyyy):"), gbc);
gbc.gridx = 1;
JTextField dateTxtFld = new JTextField(15);
addTransactionFrame.add(dateTxtFld, gbc);
// Amount (For deposit/withdrawal)
gbc.gridx = 0;
gbc.gridy = 3;
addTransactionFrame.add(new JLabel("Amount:"), gbc);
gbc.gridx = 1;
JTextField amountTxtFld = new JTextField(15);
addTransactionFrame.add(amountTxtFld, gbc);
// Apply Interest Button
JButton applyInterestBtn = new JButton("Apply Interest");
gbc.gridx = 0;
gbc.gridy = 4;
addTransactionFrame.add(applyInterestBtn, gbc);
// Submit Button
gbc.gridx = 2;
gbc.gridy = 4;
JButton submitBtn = new JButton("Submit");
addTransactionFrame.add(submitBtn, gbc);
// Transaction History
gbc.gridx = 0;
gbc.gridy = 5;
addTransactionFrame.add(new JLabel("Transaction History:"), gbc);
gbc.gridx = 1;
JTextArea transactionHistoryArea = new JTextArea(10, 40);
transactionHistoryArea.setEditable(false);
addTransactionFrame.add(new JScrollPane(transactionHistoryArea), gbc);
addTransactionFrame.setVisible(true);
// Action listener for Apply Interest button
applyInterestBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String accountNumber = acctNumTxtFld.getText();
String transactionDate = dateTxtFld.getText();
Account selectedAccount = null;
Customer selectedCustomer = null;
// Validate the date format (MM/dd/yyyy)
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/dd/yyyy");
try {
LocalDate.parse(transactionDate, formatter); // Check if the date is valid
} catch (DateTimeParseException ex) {
JOptionPane.showMessageDialog(addTransactionFrame, "Invalid date format. Please use MM/dd/yyyy.", "Error", JOptionPane.ERROR_MESSAGE);
return;
}
// Find the account and customer based on the account number
for (int i = 0; i < accounts.size(); i++) {
if (accounts.get(i).getAccountNumber().equals(accountNumber)) {
selectedAccount = accounts.get(i);
selectedCustomer = customers.get(i);
break;
}
}
// Handle interest application if account found
if (selectedAccount != null && selectedCustomer != null) {
// Apply interest to the account
selectedAccount.applyAccruedInterest(transactionDate);
// Log the interest applied transaction
String transaction = selectedAccount.logTransaction(transactionDate, "Interest Applied", 0);
// Update transaction history display
StringBuilder historyText = new StringBuilder();
for (String trans : selectedAccount.getTransactionHistory()) {
historyText.append(trans).append("\n");
}
transactionHistoryArea.setText(historyText.toString());
} else {
JOptionPane.showMessageDialog(addTransactionFrame, "Account not found.", "Error", JOptionPane.ERROR_MESSAGE);
}
}
});
// Action listener for Submit button (Deposit/Withdrawal)
submitBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
String accountNumber = acctNumTxtFld.getText();
String transactionDate = dateTxtFld.getText();
Account selectedAccount = null;
Customer selectedCustomer = null;
// Validate the date format (MM/dd/yyyy)
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MM/dd/yyyy");
try {
LocalDate.parse(transactionDate, formatter); // Check if the date is valid
} catch (DateTimeParseException ex) {
JOptionPane.showMessageDialog(addTransactionFrame, "Invalid date format. Please use MM/dd/yyyy.", "Error", JOptionPane.ERROR_MESSAGE);
return;
}
// Find the account and customer based on the account number
for (int i = 0; i < accounts.size(); i++) {
if (accounts.get(i).getAccountNumber().equals(accountNumber)) {
selectedAccount = accounts.get(i);
selectedCustomer = customers.get(i);
break;
}
}
// Handle deposit/withdrawal if account found
if (selectedAccount != null && selectedCustomer != null) {
String transactionType = "";
double amount = 0;
if (depositButton.isSelected()) {
transactionType = "Deposit";
amount = Double.parseDouble(amountTxtFld.getText());
} else if (withdrawalButton.isSelected()) {
transactionType = "Withdrawal";
amount = Double.parseDouble(amountTxtFld.getText());
}
// Process Deposit or Withdrawal
String transaction = "";
switch (transactionType) {
case "Deposit":
selectedAccount.deposit(amount);
transaction = selectedAccount.logTransaction(transactionDate, "Deposit", amount);
break;
case "Withdrawal":
selectedAccount.withdrawal(amount);
transaction = selectedAccount.logTransaction(transactionDate, "Withdrawal", amount);
break;
}
// Update the transaction history display
StringBuilder historyText = new StringBuilder();
for (String trans : selectedAccount.getTransactionHistory()) {
historyText.append(trans).append("\n");
}
transactionHistoryArea.setText(historyText.toString());
} else {
JOptionPane.showMessageDialog(addTransactionFrame, "Account not found.", "Error", JOptionPane.ERROR_MESSAGE);
}
}
});
}
private void showViewInfoPanel() {
JFrame viewInfoFrame = new JFrame("View Customer and Account Info");
viewInfoFrame.setSize(800, 600);
viewInfoFrame.setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.insets = new Insets(5, 5, 5, 5);
gbc.fill = GridBagConstraints.HORIZONTAL;
// Account Number
gbc.gridx = 0;
gbc.gridy = 0;
viewInfoFrame.add(new JLabel("Account Number:"), gbc);
gbc.gridx = 1;
JTextField acctNumTxtFld = new JTextField(15);
viewInfoFrame.add(acctNumTxtFld, gbc);
// Submit Button
gbc.gridx = 2;
gbc.gridy = 0;
JButton submitBtn = new JButton("Submit");
viewInfoFrame.add(submitBtn, gbc);
// Customer and Account Info Labels
gbc.gridx = 0;
gbc.gridy = 1;
gbc.gridwidth = 1;
viewInfoFrame.add(new JLabel("Customer ID:"), gbc);
gbc.gridx = 1;
JLabel idLabel = new JLabel();
viewInfoFrame.add(idLabel, gbc);
gbc.gridx = 0;
gbc.gridy = 2;
viewInfoFrame.add(new JLabel("SSN:"), gbc);
gbc.gridx = 1;
JLabel ssnLabel = new JLabel();
viewInfoFrame.add(ssnLabel, gbc);
gbc.gridx = 0;
gbc.gridy = 3;
viewInfoFrame.add(new JLabel("Last Name:"), gbc);
gbc.gridx = 1;
JLabel lastNameLabel = new JLabel();
viewInfoFrame.add(lastNameLabel, gbc);
gbc.gridx = 0;
gbc.gridy = 4;
viewInfoFrame.add(new JLabel("First Name:"), gbc);
gbc.gridx = 1;
JLabel firstNameLabel = new JLabel();
viewInfoFrame.add(firstNameLabel, gbc);
gbc.gridx = 0;
gbc.gridy = 5;
viewInfoFrame.add(new JLabel("Street Address:"), gbc);
gbc.gridx = 1;
JLabel streetLabel = new JLabel();
viewInfoFrame.add(streetLabel, gbc);
gbc.gridx = 0;
gbc.gridy = 6;
viewInfoFrame.add(new JLabel("City:"), gbc);
gbc.gridx = 1;
JLabel cityLabel = new JLabel();
viewInfoFrame.add(cityLabel, gbc);
gbc.gridx = 0;
gbc.gridy = 7;
viewInfoFrame.add(new JLabel("State:"), gbc);
gbc.gridx = 1;
JLabel stateLabel = new JLabel();
viewInfoFrame.add(stateLabel, gbc);
gbc.gridx = 0;
gbc.gridy = 8;
viewInfoFrame.add(new JLabel("ZIP Code:"), gbc);
gbc.gridx = 1;
JLabel zipLabel = new JLabel();
viewInfoFrame.add(zipLabel, gbc);
gbc.gridx = 0;
gbc.gridy = 9;
viewInfoFrame.add(new JLabel("Phone:"), gbc);
gbc.gridx = 1;
JLabel phoneLabel = new JLabel();
viewInfoFrame.add(phoneLabel, gbc);
gbc.gridx = 0;
gbc.gridy = 10;
viewInfoFrame.add(new JLabel("Account Type:"), gbc);
gbc.gridx = 1;
JLabel acctTypeLabel = new JLabel();
viewInfoFrame.add(acctTypeLabel, gbc);
gbc.gridx = 0;
gbc.gridy = 11;
viewInfoFrame.add(new JLabel("Balance:"), gbc);
gbc.gridx = 1;
JLabel balanceLabel = new JLabel();
viewInfoFrame.add(balanceLabel, gbc);
// Transaction History Section
gbc.gridx = 0;
gbc.gridy = 12;
viewInfoFrame.add(new JLabel("Transaction History:"), gbc);
gbc.gridx = 1;
gbc.gridy = 12;
gbc.gridwidth = 3;
JTextArea transactionHistoryArea = new JTextArea(10, 40);
transactionHistoryArea.setEditable(false);
JScrollPane scrollPane = new JScrollPane(transactionHistoryArea);
viewInfoFrame.add(scrollPane, gbc);
// Done Button
JButton doneBtn = new JButton("Done");
gbc.gridx = 2;
gbc.gridy = 13;
viewInfoFrame.add(doneBtn, gbc);
viewInfoFrame.setVisible(true);
// Add action listener for the submit button
submitBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
// Retrieve and display customer and account info
String accountNumber = acctNumTxtFld.getText();
Account selectedAccount = null;
Customer selectedCustomer = null;
for (int i = 0; i < accounts.size(); i++) {
if (accounts.get(i).getAccountNumber().equals(accountNumber)) {
selectedAccount = accounts.get(i);
selectedCustomer = customers.get(i);
break;
}
}
if (selectedAccount != null && selectedCustomer != null) {
idLabel.setText(selectedCustomer.getID());
ssnLabel.setText(selectedCustomer.getSSN());
lastNameLabel.setText(selectedCustomer.getLastName());
firstNameLabel.setText(selectedCustomer.getFirstName());
streetLabel.setText(selectedCustomer.getStreet());
cityLabel.setText(selectedCustomer.getCity());
stateLabel.setText(selectedCustomer.getState());
zipLabel.setText(selectedCustomer.getZip());
phoneLabel.setText(selectedCustomer.getPhone());
acctTypeLabel.setText(selectedAccount.getAccountType());
balanceLabel.setText(String.format("$%.2f", selectedAccount.getBalance()));
// Populate transaction history
StringBuilder transactionHistoryText = new StringBuilder();
for (String transaction : selectedAccount.getTransactionHistory()) {
transactionHistoryText.append(transaction).append("\n");
}
transactionHistoryArea.setText(transactionHistoryText.toString());
} else {
JOptionPane.showMessageDialog(viewInfoFrame, "Account not found.", "Error", JOptionPane.ERROR_MESSAGE);
}
}
});
// Add action listener for the done button
doneBtn.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
viewInfoFrame.dispose(); // Close the window when done is clicked
}
});
}
public static void main(String[] args) {
ArrayList<Customer> customers = new ArrayList<>();
ArrayList<Account> accounts = new ArrayList<>();
new BankAcctAppGUI(customers, accounts);
}
}

View File

@ -1,8 +1,8 @@
/* Phase III */
/* Phase IV */
package bankAcctApp;
// Class representing checking accounts
//Class representing checking accounts
public class CheckingAccount extends Account {
// Overridden method for withdrawals in checking accounts
@ -39,4 +39,5 @@ public class CheckingAccount extends Account {
public double balance() {
return getBalance(); // Return the current balance
}
}
}

View File

@ -1,4 +1,4 @@
/* Phase III */
/* Phase IV */
package bankAcctApp;
@ -108,4 +108,7 @@ public class Customer {
id, lastName, firstName, ssn, phone, street, city, state, zip
);
}
public Object getAccountNumber() {
return null;
}
}

View File

@ -1,4 +1,4 @@
/* Phase III */
/* Phase IV */
package bankAcctApp;
@ -73,7 +73,7 @@ public class DataEntry {
return input;
}
// Static method to validate decimals.
// Static method to validate decimals (specific to the CLI)
public static double inputDecimal(String prompt) {
boolean isValid = false;
double decimalValue = 0.0;
@ -91,7 +91,7 @@ public class DataEntry {
return decimalValue;
}
// Static method to validate decimals are within a range.
// Static method to validate decimals are within a range (specific to the CLI)
public static double inputDecimalInRange(String prompt, double min, double max) {
double value;
do {
@ -105,6 +105,7 @@ public class DataEntry {
return value;
}
// Static method to validate a date in MM/DD/YYYY format.
public static String inputDate(String prompt) {
Pattern patternDate = Pattern.compile("^(0[1-9]|1[0-2])/(0[1-9]|[12][0-9]|3[01])/(\\d{4})$");
@ -121,4 +122,91 @@ public class DataEntry {
}
return date;
}
// Validation methods specific to the GUI
// Reusable patterns for string v // Reusable patterns for string validation (no prompt messages, just validation)
private static final Pattern patternID = Pattern.compile("[A-Z0-9]{5}");
private static final Pattern patternSSN = Pattern.compile("[0-9]{9}");
private static final Pattern patternName = Pattern.compile("[A-Za-z\\s,\\.\\-']{1,20}");
private static final Pattern patternStreet = Pattern.compile("[0-9]+[A-Za-z\\s,\\.\\-]{1,19}");
private static final Pattern patternCity = Pattern.compile("[A-Za-z\\s]{1,20}");
private static final Pattern patternState = Pattern.compile("[A-Z]{2}");
private static final Pattern patternZip = Pattern.compile("[0-9]{5}");
private static final Pattern patternPhone = Pattern.compile("[0-9]{10}");
// Validate input for strings using regex (for GUI)
private static void validateInput(Pattern pattern, String input) {
if (!pattern.matcher(input).matches()) {
throw new IllegalArgumentException("Invalid input: " + input);
}
}
// Validate and convert string input to double
private static double validateAndConvertToDouble(String input) {
try {
return Double.parseDouble(input); // Convert to double
} catch (NumberFormatException ex) {
throw new IllegalArgumentException("Invalid decimal input: " + input);
}
}
// Validate and convert decimal numbers for account information within a range (for GUI)
public static double inputDecimalInRangeGUI(String input, double min, double max) {
double value = validateAndConvertToDouble(input); // Validate as double
if (value < min || value > max) {
throw new IllegalArgumentException("Value out of range: " + value);
}
return value;
}
// Validate decimal input (no range validation)
public static double inputDecimalGUI(String input) {
return validateAndConvertToDouble(input); // Simply convert the valid decimal input
}
// Field-specific validation methods for GUI
public static void inputIDGUI(String id) {
validateInput(patternID, id); // Validate ID format
}
public static void inputSSNGUI(String ssn) {
validateInput(patternSSN, ssn); // Validate SSN format
}
public static void inputLastNameGUI(String lastName) {
validateInput(patternName, lastName); // Validate last name format
}
public static void inputFirstNameGUI(String firstName) {
validateInput(patternName, firstName); // Validate first name format
}
public static void inputStreetGUI(String street) {
validateInput(patternStreet, street); // Validate street format
}
public static void inputCityGUI(String city) {
validateInput(patternCity, city); // Validate city format
}
public static void inputStateGUI(String state) {
validateInput(patternState, state); // Validate state format
}
public static void inputZipGUI(String zip) {
validateInput(patternZip, zip); // Validate zip format
}
public static void inputPhoneGUI(String phone) {
validateInput(patternPhone, phone); // Validate phone format
}
// For numeric string validation (e.g., for account number)
public static void inputNumericStringGUI(String input, int length) {
if (input.length() != length || !input.matches("[0-9]+")) {
throw new IllegalArgumentException("Invalid numeric input. Must be " + length + " digits.");
}
}
}

View File

@ -1,8 +1,8 @@
/* Phase III */
/* Phase IV */
package bankAcctApp;
// Class representing savings accounts
//Class representing savings accounts
public class SavingsAccount extends Account {
// Overridden method for withdrawals in savings accounts
@ -38,4 +38,4 @@ public class SavingsAccount extends Account {
public double balance() {
return getBalance(); // Return the current balance
}
}
}