From cc7a015cfeafd302b1974bf3568d06d063a7502f Mon Sep 17 00:00:00 2001 From: HATEGEKIMANA Shema Arafati Date: Mon, 3 Nov 2025 18:35:50 +0200 Subject: [PATCH] Add advanced transaction tracking and insights features --- src/Bank/Bank.java | 322 ++++++++++++++++++-------------- src/Bank/BankAccount.java | 153 ++++++++++----- src/Bank/CurrentAccount.java | 32 ++-- src/Bank/SavingsAccount.java | 93 +++++---- src/Bank/StudentAccount.java | 29 +-- src/Bank/Transaction.java | 55 ++++++ src/Bank/TransactionType.java | 20 ++ src/GUI/AddCurrentAccount.java | 269 +++++++++++++------------- src/GUI/AddSavingsAccount.java | 262 +++++++++++++------------- src/GUI/AddStudentAccount.java | 271 +++++++++++++-------------- src/GUI/DepositAcc.java | 255 ++++++++++++------------- src/GUI/DisplayList.java | 162 +++++++++++----- src/GUI/GUIForm.java | 42 +++-- src/GUI/InsightsDashboard.java | 176 +++++++++++++++++ src/GUI/Menu.java | 297 +++++++++++++++-------------- src/GUI/TransactionHistory.java | 162 ++++++++++++++++ src/GUI/TransferFunds.java | 143 ++++++++++++++ src/GUI/WithdrawAcc.java | 273 +++++++++++++-------------- 18 files changed, 1870 insertions(+), 1146 deletions(-) create mode 100644 src/Bank/Transaction.java create mode 100644 src/Bank/TransactionType.java create mode 100644 src/GUI/InsightsDashboard.java create mode 100644 src/GUI/TransactionHistory.java create mode 100644 src/GUI/TransferFunds.java diff --git a/src/Bank/Bank.java b/src/Bank/Bank.java index 2c99b23..ebbddd2 100644 --- a/src/Bank/Bank.java +++ b/src/Bank/Bank.java @@ -1,153 +1,189 @@ package Bank; + import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.Locale; +import java.util.stream.Collectors; + import javax.swing.DefaultListModel; + import Exceptions.AccNotFound; import Exceptions.InvalidAmount; import Exceptions.MaxBalance; import Exceptions.MaxWithdraw; public class Bank implements Serializable { - /** - * - */ - private static final long serialVersionUID = 1L; - private BankAccount[] accounts= new BankAccount[100]; - public int addAccount(BankAccount acc) - { - int i=0; - for(i=0;i<100;i++) - { - if(getAccounts()[i]==null) - { - break; - } - } - getAccounts()[i]=acc; - return i; - } - - public int addAccount(String name, double balance, double maxWithLimit ) - { - SavingsAccount acc=new SavingsAccount(name, balance, maxWithLimit); - return this.addAccount(acc); - } - - public int addAccount(String name, double balance, String tradeLicense) throws Exception - { - CurrentAccount acc = new CurrentAccount(name, balance,tradeLicense); - return this.addAccount(acc); - } - - public int addAccount(String name, String institutionName, double balance, double min_balance) - { - StudentAccount acc= new StudentAccount(name,balance,institutionName); - return this.addAccount(acc); - } - - public BankAccount findAccount(String aacountNum) - { - int i; - for(i=0;i<100;i++) - { - if(getAccounts()[i]==null) - { - break; - } - if(getAccounts()[i].acc_num.equals(aacountNum)) - { - return getAccounts()[i]; - } - - } - return null; - } - - public void deposit(String aacountNum, double amt) throws InvalidAmount,AccNotFound - - { - if(amt<0) - { - throw new InvalidAmount("Invalid Deposit amount"); - } - BankAccount temp=findAccount(aacountNum); - if(temp==null) - { - throw new AccNotFound("Account Not Found"); - } - if(temp!=null) - { - temp.deposit(amt); - - } - - } - - - public void withdraw(String aacountNum, double amt) throws MaxBalance,AccNotFound, MaxWithdraw, InvalidAmount - { - BankAccount temp=findAccount(aacountNum); - - if(temp==null) - { - throw new AccNotFound("Account Not Found"); - } - - if(amt<=0) - { - throw new InvalidAmount("Invalid Amount"); - } - - if(amt>temp.getbalance()) - { - throw new MaxBalance("Insufficient Balance"); - } - if(temp!=null) - { - temp.withdraw(amt); - } - } - - public DefaultListModel display() - { - DefaultListModel list=new DefaultListModel(); - int i; -// String type=null; - - for(i=0;i<100;i++) - { - if(getAccounts()[i]==null) - { - break; - } -// if(getAccounts()[i].getClass().toString().equals("class Bank.SavingsAccount")) -// { -// type="Type: Savings Account"; -// } -// -// else if(getAccounts()[i].getClass().toString().equals("class Bank.CurrentAccount")) -// { -// type="Type: Current Account"; -// } -// -// else if(getAccounts()[i].getClass().toString().equals("class Bank.StudentAccount")) -// { -// type="Type: Student Account"; -// } - - list.addElement(getAccounts()[i].toString()); - - - } - - return list; - } - - public BankAccount[] getAccounts() { - return accounts; - } - - public void setAccounts(BankAccount[] accounts) { - this.accounts = accounts; - } - + /** + * + */ + private static final long serialVersionUID = 1L; + private final List accounts = new ArrayList<>(); + + public synchronized int addAccount(BankAccount acc) { + accounts.add(acc); + return accounts.size() - 1; + } + + public synchronized int addAccount(String name, double balance, double maxWithLimit) { + SavingsAccount acc = new SavingsAccount(name, balance, maxWithLimit); + return this.addAccount(acc); + } + + public synchronized int addAccount(String name, double balance, String tradeLicense) { + CurrentAccount acc = new CurrentAccount(name, balance, tradeLicense); + return this.addAccount(acc); + } + + public synchronized int addAccount(String name, String institutionName, double balance, double min_balance) { + StudentAccount acc = new StudentAccount(name, balance, institutionName); + return this.addAccount(acc); + } + + public synchronized BankAccount findAccount(String accountNum) { + if (accountNum == null) { + return null; + } + for (BankAccount account : accounts) { + if (account.getAccountNumber().equalsIgnoreCase(accountNum)) { + return account; + } + } + return null; + } + + private BankAccount requireAccount(String accountNumber) throws AccNotFound { + BankAccount account = findAccount(accountNumber); + if (account == null) { + throw new AccNotFound("Account Not Found"); + } + return account; + } + + public synchronized void deposit(String accountNum, double amount) throws InvalidAmount, AccNotFound { + deposit(accountNum, amount, "Deposit"); + } + + public synchronized void deposit(String accountNum, double amount, String description) + throws InvalidAmount, AccNotFound { + if (amount <= 0) { + throw new InvalidAmount("Invalid Deposit amount"); + } + BankAccount account = requireAccount(accountNum); + account.deposit(amount, description, TransactionType.DEPOSIT); + } + + public synchronized void withdraw(String accountNum, double amount) + throws MaxBalance, AccNotFound, MaxWithdraw, InvalidAmount { + withdraw(accountNum, amount, "Withdrawal"); + } + + public synchronized void withdraw(String accountNum, double amount, String description) + throws MaxBalance, AccNotFound, MaxWithdraw, InvalidAmount { + BankAccount account = requireAccount(accountNum); + + if (amount <= 0) { + throw new InvalidAmount("Invalid Amount"); + } + + if (amount > account.getbalance()) { + throw new MaxBalance("Insufficient Balance"); + } + account.withdraw(amount, description, TransactionType.WITHDRAWAL); + } + + public synchronized void transfer(String fromAccount, String toAccount, double amount, String note) + throws MaxBalance, AccNotFound, MaxWithdraw, InvalidAmount { + if (fromAccount.equalsIgnoreCase(toAccount)) { + throw new InvalidAmount("Cannot transfer to the same account"); + } + if (amount <= 0) { + throw new InvalidAmount("Transfer amount must be greater than zero"); + } + BankAccount source = requireAccount(fromAccount); + BankAccount target = requireAccount(toAccount); + + String outgoingNote = String.format("Transfer to %s (%s)%s", target.getOwnerName(), + target.getAccountNumber(), + note == null || note.isEmpty() ? "" : " - " + note); + String incomingNote = String.format("Transfer from %s (%s)%s", source.getOwnerName(), + source.getAccountNumber(), + note == null || note.isEmpty() ? "" : " - " + note); + + source.withdraw(amount, outgoingNote, TransactionType.TRANSFER_OUT); + target.deposit(amount, incomingNote, TransactionType.TRANSFER_IN); + } + + public synchronized DefaultListModel display() { + DefaultListModel list = new DefaultListModel(); + for (BankAccount account : accounts) { + list.addElement(String.format(Locale.US, "%s | %s | %s | Balance: %.2f", account.getOwnerName(), + account.getAccountNumber(), account.getAccountType(), account.getbalance())); + } + return list; + } + + public synchronized List getAccountsSnapshot() { + return Collections.unmodifiableList(new ArrayList<>(accounts)); + } + + public synchronized List getTransactions(String accountNumber) throws AccNotFound { + return requireAccount(accountNumber).getTransactions(); + } + + public synchronized List getRecentTransactions(int limit) { + return accounts.stream() + .flatMap(account -> account.getTransactions().stream()) + .sorted(Comparator.comparing(Transaction::getTimestamp).reversed()) + .limit(limit) + .collect(Collectors.toList()); + } + + public synchronized List searchAccounts(String query) { + if (query == null || query.isEmpty()) { + return getAccountsSnapshot(); + } + final String normalized = query.toLowerCase(Locale.US); + return accounts.stream() + .filter(account -> account.getOwnerName().toLowerCase(Locale.US).contains(normalized) + || account.getAccountNumber().toLowerCase(Locale.US) + .contains(normalized)) + .collect(Collectors.toList()); + } + + public synchronized double getTotalBalance() { + return accounts.stream().mapToDouble(BankAccount::getbalance).sum(); + } + + public synchronized int getTotalCustomers() { + return accounts.size(); + } + + public synchronized double getAverageBalance() { + if (accounts.isEmpty()) { + return 0; + } + return getTotalBalance() / accounts.size(); + } + + public synchronized List getTopAccountsByBalance(int limit) { + return accounts.stream().sorted(Comparator.comparingDouble(BankAccount::getbalance).reversed()) + .limit(limit).collect(Collectors.toList()); + } + + public synchronized long countAccountsByType(Class type) { + return accounts.stream().filter(type::isInstance).count(); + } + + public synchronized BankAccount[] getAccounts() { + return accounts.toArray(new BankAccount[0]); + } + + public synchronized void setAccounts(List accounts) { + this.accounts.clear(); + this.accounts.addAll(accounts); + } } + diff --git a/src/Bank/BankAccount.java b/src/Bank/BankAccount.java index d27fd7e..ce2b9c5 100644 --- a/src/Bank/BankAccount.java +++ b/src/Bank/BankAccount.java @@ -1,62 +1,113 @@ package Bank; + import java.io.Serializable; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.UUID; +import Exceptions.InvalidAmount; import Exceptions.MaxBalance; import Exceptions.MaxWithdraw; public class BankAccount implements Serializable { - /** - * - */ - private static final long serialVersionUID = 1L; - private String name; - private double balance; - private double min_balance; - private String acc_num; - //String type; - - - public BankAccount(String name, double balance, double min_balance) throws Exception { - if (balance < min_balance) { - throw new Exception("Initial balance cannot be less than the minimum required balance: " + min_balance); - } - this.name = name; - this.balance = balance; - this.min_balance = min_balance; - this.acc_num = 10000 + (int) (Math.random() * 89999) + ""; -} + /** + * + */ + private static final long serialVersionUID = 1L; + private final String name; + private final String acc_num; + protected double balance; + protected double min_balance; + private final List transactions = new ArrayList<>(); + + public BankAccount(String name, double balance, double min_balance) { + if (balance < min_balance) { + throw new IllegalArgumentException( + "Initial balance cannot be less than the minimum required balance: " + min_balance); + } + this.name = name; + this.balance = balance; + this.min_balance = min_balance; + this.acc_num = generateAccountNumber(); + recordTransaction(TransactionType.ACCOUNT_CREATED, balance, + "Account created with an initial deposit"); + } + + private String generateAccountNumber() { + return "AC" + UUID.randomUUID().toString().substring(0, 8).toUpperCase(); + } + + public void deposit(double amount) throws InvalidAmount { + deposit(amount, "Deposit"); + } + + public void deposit(double amount, String description) throws InvalidAmount { + deposit(amount, description, TransactionType.DEPOSIT); + } + + public void deposit(double amount, String description, TransactionType type) throws InvalidAmount { + if (amount <= 0) { + throw new InvalidAmount("Deposit amount must be greater than zero."); + } + balance += amount; + recordTransaction(type, amount, description); + } + + public void withdraw(double amount) throws MaxWithdraw, MaxBalance { + withdraw(amount, "Withdrawal"); + } + + public void withdraw(double amount, String description) throws MaxWithdraw, MaxBalance { + withdraw(amount, description, TransactionType.WITHDRAWAL); + } + + public void withdraw(double amount, String description, TransactionType type) throws MaxWithdraw, MaxBalance { + if ((balance - amount) >= min_balance && amount <= balance) { + balance -= amount; + recordTransaction(type, amount, description); + } + + else { + throw new MaxBalance("Insufficient Balance"); + } + } + + protected void recordTransaction(TransactionType type, double amount, String description) { + transactions.add(new Transaction(type, amount, balance, description)); + } + + public double getbalance() { + return balance; + } + + public String getAccountNumber() { + return acc_num; + } + + public String getOwnerName() { + return name; + } + + public double getMinBalance() { + return min_balance; + } + + protected void setMinBalance(double min_balance) { + this.min_balance = min_balance; + } + + public List getTransactions() { + return Collections.unmodifiableList(transactions); + } + public String getAccountType() { + return getClass().getSimpleName().replace("Account", " Account").trim(); + } - public void deposit(double amount) throws InvalidAmount - { - if (amount <= 0){ - throw new InvalidAmount("Deposit amount must be greater than zero."); - } - balance+=amount; - } - - public void withdraw(double amount) throws MaxWithdraw, MaxBalance - { - if((balance-amount)>=min_balance && amount arr = new DefaultListModel(); - private JPanel contentPane; - - - /** - * Create the frame. - */ - @SuppressWarnings({ }) - public DisplayList() { - setTitle("Account List"); - setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); - setBounds(100, 100, 649, 474); - contentPane = new JPanel(); - contentPane.setBackground(SystemColor.activeCaption); - contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); - setContentPane(contentPane); - contentPane.setLayout(null); - - JLabel lblAccountList = new JLabel("Account List"); - lblAccountList.setFont(new Font("Tahoma", Font.BOLD, 18)); - lblAccountList.setHorizontalAlignment(SwingConstants.CENTER); - lblAccountList.setBounds(0, 11, 623, 31); - contentPane.add(lblAccountList); - - JScrollPane scrollPane = new JScrollPane(); - scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); - scrollPane.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_ALWAYS); - scrollPane.setBounds(10, 66, 613, 358); - contentPane.add(scrollPane); - - arr=FileIO.bank.display(); - JList list = new JList(arr); - scrollPane.setViewportView(list); - - - - } + /** + * + */ + private static final long serialVersionUID = 1L; + static DefaultListModel arr = new DefaultListModel(); + private JPanel contentPane; + private JTextField searchField; + private JList list; + private JLabel totalBalanceLabel; + private JLabel totalAccountsLabel; + + public DisplayList() { + setTitle("Account Directory"); + setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + setBounds(100, 100, 720, 520); + contentPane = new JPanel(); + contentPane.setBackground(SystemColor.activeCaption); + contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); + setContentPane(contentPane); + contentPane.setLayout(null); + + JLabel lblAccountList = new JLabel("Account Directory"); + lblAccountList.setFont(new Font("Tahoma", Font.BOLD, 18)); + lblAccountList.setHorizontalAlignment(SwingConstants.CENTER); + lblAccountList.setBounds(10, 11, 684, 31); + contentPane.add(lblAccountList); + + searchField = new JTextField(); + searchField.setBounds(20, 53, 300, 25); + contentPane.add(searchField); + searchField.setColumns(10); + + JButton btnSearch = new JButton("Search"); + btnSearch.setBounds(330, 53, 100, 25); + btnSearch.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + populateList(FileIO.bank.searchAccounts(searchField.getText())); + } + }); + contentPane.add(btnSearch); + + JButton btnReset = new JButton("Reset"); + btnReset.setBounds(440, 53, 100, 25); + btnReset.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + searchField.setText(null); + populateList(FileIO.bank.getAccountsSnapshot()); + } + }); + contentPane.add(btnReset); + + JButton btnRefresh = new JButton("Refresh"); + btnRefresh.setBounds(550, 53, 100, 25); + btnRefresh.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + populateList(FileIO.bank.getAccountsSnapshot()); + } + }); + contentPane.add(btnRefresh); + + JScrollPane scrollPane = new JScrollPane(); + scrollPane.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS); + scrollPane.setBounds(20, 115, 674, 320); + contentPane.add(scrollPane); + + arr = new DefaultListModel<>(); + list = new JList<>(arr); + list.setFont(new Font("Monospaced", Font.PLAIN, 12)); + scrollPane.setViewportView(list); + + totalAccountsLabel = new JLabel(); + totalAccountsLabel.setBounds(20, 446, 250, 25); + contentPane.add(totalAccountsLabel); + + totalBalanceLabel = new JLabel(); + totalBalanceLabel.setHorizontalAlignment(SwingConstants.RIGHT); + totalBalanceLabel.setBounds(394, 446, 300, 25); + contentPane.add(totalBalanceLabel); + + populateList(FileIO.bank.getAccountsSnapshot()); + } + + private void populateList(List accounts) { + arr.clear(); + for (BankAccount account : accounts) { + arr.addElement(String.format("%-25s %-15s %-18s Balance: %10.2f", account.getOwnerName(), + account.getAccountNumber(), account.getAccountType(), account.getbalance())); + } + + if (list != null) { + list.setModel(arr); + } + totalAccountsLabel.setText("Accounts: " + FileIO.bank.getTotalCustomers()); + totalBalanceLabel.setText(String.format("Total balance: %.2f", FileIO.bank.getTotalBalance())); + } } + diff --git a/src/GUI/GUIForm.java b/src/GUI/GUIForm.java index 568e83e..0cd94ea 100644 --- a/src/GUI/GUIForm.java +++ b/src/GUI/GUIForm.java @@ -9,27 +9,35 @@ public class GUIForm { public static AddCurrentAccount addcurrentacc= new AddCurrentAccount(); public static AddSavingsAccount addsavingsaccount = new AddSavingsAccount(); public static AddStudentAccount addstudentaccount = new AddStudentAccount(); - public static DisplayList displaylist= new DisplayList(); - public static DepositAcc depositacc= new DepositAcc(); - public static WithdrawAcc withdraw = new WithdrawAcc(); + public static DisplayList displaylist= new DisplayList(); + public static DepositAcc depositacc= new DepositAcc(); + public static WithdrawAcc withdraw = new WithdrawAcc(); + public static TransferFunds transferFunds = new TransferFunds(); + public static TransactionHistory transactionHistory = new TransactionHistory(); + public static InsightsDashboard insightsDashboard = new InsightsDashboard(); public static void UpdateDisplay() { - if(displaylist.isVisible()) - { - Point O= displaylist.getLocation(); - displaylist.dispose(); - displaylist = new DisplayList(); - displaylist.setVisible(true); - displaylist.setLocation(O);; - } - - else { - displaylist = new DisplayList(); - } - - } + if(displaylist.isVisible()) + { + Point O= displaylist.getLocation(); + displaylist.dispose(); + displaylist = new DisplayList(); + displaylist.setVisible(true); + displaylist.setLocation(O);; + } + + else { + displaylist = new DisplayList(); + } + + if(insightsDashboard.isVisible()) + { + insightsDashboard.refreshDataView(); + } + + } } diff --git a/src/GUI/InsightsDashboard.java b/src/GUI/InsightsDashboard.java new file mode 100644 index 0000000..6ffdd2c --- /dev/null +++ b/src/GUI/InsightsDashboard.java @@ -0,0 +1,176 @@ +package GUI; + +import java.awt.Font; +import java.awt.SystemColor; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.List; + +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.SwingConstants; +import javax.swing.border.EmptyBorder; +import javax.swing.table.DefaultTableModel; + +import Bank.BankAccount; +import Bank.CurrentAccount; +import Bank.SavingsAccount; +import Bank.StudentAccount; +import Bank.Transaction; +import Bank.TransactionType; +import Data.FileIO; + +public class InsightsDashboard extends JFrame { + + private static final long serialVersionUID = 1L; + private JPanel contentPane; + private JLabel totalBalanceLabel; + private JLabel totalCustomersLabel; + private JLabel averageBalanceLabel; + private JLabel savingsCountLabel; + private JLabel currentCountLabel; + private JLabel studentCountLabel; + private DefaultTableModel topAccountsModel; + private DefaultTableModel recentTransactionsModel; + + public InsightsDashboard() { + setTitle("Bank Insights"); + setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + setBounds(100, 100, 820, 600); + contentPane = new JPanel(); + contentPane.setBackground(SystemColor.activeCaption); + contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); + setContentPane(contentPane); + contentPane.setLayout(null); + + JLabel title = new JLabel("Insights & Analytics"); + title.setHorizontalAlignment(SwingConstants.CENTER); + title.setFont(new Font("Tahoma", Font.BOLD, 22)); + title.setBounds(10, 11, 784, 30); + contentPane.add(title); + + totalBalanceLabel = new JLabel(); + totalBalanceLabel.setFont(new Font("Tahoma", Font.BOLD, 14)); + totalBalanceLabel.setBounds(20, 60, 250, 25); + contentPane.add(totalBalanceLabel); + + totalCustomersLabel = new JLabel(); + totalCustomersLabel.setFont(new Font("Tahoma", Font.BOLD, 14)); + totalCustomersLabel.setBounds(290, 60, 200, 25); + contentPane.add(totalCustomersLabel); + + averageBalanceLabel = new JLabel(); + averageBalanceLabel.setFont(new Font("Tahoma", Font.BOLD, 14)); + averageBalanceLabel.setBounds(520, 60, 250, 25); + contentPane.add(averageBalanceLabel); + + savingsCountLabel = new JLabel(); + savingsCountLabel.setBounds(20, 95, 220, 20); + contentPane.add(savingsCountLabel); + + currentCountLabel = new JLabel(); + currentCountLabel.setBounds(290, 95, 220, 20); + contentPane.add(currentCountLabel); + + studentCountLabel = new JLabel(); + studentCountLabel.setBounds(520, 95, 220, 20); + contentPane.add(studentCountLabel); + + JLabel topAccountsLabel = new JLabel("Top Accounts"); + topAccountsLabel.setFont(new Font("Tahoma", Font.BOLD, 14)); + topAccountsLabel.setBounds(20, 130, 200, 20); + contentPane.add(topAccountsLabel); + + topAccountsModel = new DefaultTableModel(new Object[] { "Owner", "Account", "Type", "Balance" }, 0) { + private static final long serialVersionUID = 1L; + + @Override + public boolean isCellEditable(int row, int column) { + return false; + } + }; + JTable topAccountsTable = new JTable(topAccountsModel); + topAccountsTable.getTableHeader().setFont(new Font("Tahoma", Font.BOLD, 12)); + JScrollPane topAccountsScroll = new JScrollPane(topAccountsTable); + topAccountsScroll.setBounds(20, 160, 360, 220); + contentPane.add(topAccountsScroll); + + JLabel recentTransactionsLabel = new JLabel("Recent Transactions"); + recentTransactionsLabel.setFont(new Font("Tahoma", Font.BOLD, 14)); + recentTransactionsLabel.setBounds(410, 130, 200, 20); + contentPane.add(recentTransactionsLabel); + + recentTransactionsModel = new DefaultTableModel( + new Object[] { "Date", "Account", "Type", "Amount" }, 0) { + private static final long serialVersionUID = 1L; + + @Override + public boolean isCellEditable(int row, int column) { + return false; + } + }; + JTable recentTransactionsTable = new JTable(recentTransactionsModel); + recentTransactionsTable.getTableHeader().setFont(new Font("Tahoma", Font.BOLD, 12)); + JScrollPane recentTransactionsScroll = new JScrollPane(recentTransactionsTable); + recentTransactionsScroll.setBounds(410, 160, 384, 220); + contentPane.add(recentTransactionsScroll); + + JButton refreshButton = new JButton("Refresh Data"); + refreshButton.setBounds(20, 410, 150, 30); + refreshButton.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + refreshData(); + } + }); + contentPane.add(refreshButton); + + refreshData(); + } + + private void refreshData() { + totalBalanceLabel.setText(String.format("Total Balance: %.2f", FileIO.bank.getTotalBalance())); + totalCustomersLabel.setText("Customers: " + FileIO.bank.getTotalCustomers()); + averageBalanceLabel.setText(String.format("Average Balance: %.2f", FileIO.bank.getAverageBalance())); + savingsCountLabel.setText("Savings Accounts: " + FileIO.bank.countAccountsByType(SavingsAccount.class)); + currentCountLabel.setText("Current Accounts: " + FileIO.bank.countAccountsByType(CurrentAccount.class)); + studentCountLabel.setText("Student Accounts: " + FileIO.bank.countAccountsByType(StudentAccount.class)); + + List topAccounts = FileIO.bank.getTopAccountsByBalance(5); + topAccountsModel.setRowCount(0); + for (BankAccount account : topAccounts) { + topAccountsModel.addRow(new Object[] { account.getOwnerName(), account.getAccountNumber(), + account.getAccountType(), String.format("%.2f", account.getbalance()) }); + } + + List recentTransactions = FileIO.bank.getRecentTransactions(10); + recentTransactionsModel.setRowCount(0); + for (Transaction transaction : recentTransactions) { + recentTransactionsModel.addRow(new Object[] { transaction.getFormattedTimestamp(), + findAccountNumber(transaction), formatType(transaction.getType()), + String.format("%.2f", transaction.getAmount()) }); + } + } + + private String findAccountNumber(Transaction transaction) { + for (BankAccount account : FileIO.bank.getAccountsSnapshot()) { + if (account.getTransactions().contains(transaction)) { + return account.getAccountNumber(); + } + } + return "-"; + } + + private String formatType(TransactionType type) { + String raw = type.name().toLowerCase().replace('_', ' '); + return Character.toUpperCase(raw.charAt(0)) + raw.substring(1); + } + + public void refreshDataView() { + refreshData(); + } +} + diff --git a/src/GUI/Menu.java b/src/GUI/Menu.java index 29a97b5..221fcf7 100644 --- a/src/GUI/Menu.java +++ b/src/GUI/Menu.java @@ -1,161 +1,158 @@ package GUI; + +import java.awt.Font; +import java.awt.SystemColor; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.JButton; import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JOptionPane; import javax.swing.JPanel; +import javax.swing.SwingConstants; import javax.swing.border.EmptyBorder; import Data.FileIO; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import java.awt.Font; -import java.awt.Image; +public class Menu extends JFrame { -import javax.swing.JButton; -import javax.swing.SwingConstants; -import java.awt.event.ActionListener; -import java.awt.event.ActionEvent; -import java.awt.SystemColor; -import javax.swing.ImageIcon; -import javax.swing.Icon; + /** + * + */ + private static final long serialVersionUID = 1L; + private JPanel contentPane; -public class Menu extends JFrame { + public Menu() { + setTitle("Banking System"); + setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); + setBounds(100, 100, 720, 520); + contentPane = new JPanel(); + contentPane.setBackground(SystemColor.activeCaption); + contentPane.setForeground(SystemColor.activeCaption); + contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); + setContentPane(contentPane); + contentPane.setLayout(null); + + JLabel lblBankingSystem = new JLabel("Digital Banking Command Center"); + lblBankingSystem.setHorizontalAlignment(SwingConstants.CENTER); + lblBankingSystem.setFont(new Font("Tahoma", Font.BOLD, 24)); + lblBankingSystem.setBounds(20, 30, 664, 46); + contentPane.add(lblBankingSystem); + + JLabel lblSubtitle = new JLabel("Manage accounts, cash flow and insights from a single place"); + lblSubtitle.setHorizontalAlignment(SwingConstants.CENTER); + lblSubtitle.setFont(new Font("Tahoma", Font.PLAIN, 14)); + lblSubtitle.setBounds(20, 75, 664, 25); + contentPane.add(lblSubtitle); + + JButton btnAddAccount = new JButton("Add Account"); + btnAddAccount.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (!GUIForm.addaccount.isVisible()) { + GUIForm.addaccount.setVisible(true); + } else { + JOptionPane.showMessageDialog(getComponent(0), "Already Opened", "Warning", 0); + } + + } + }); + btnAddAccount.setBounds(120, 140, 200, 40); + contentPane.add(btnAddAccount); + + JButton btnDepositToAccount = new JButton("Deposit"); + btnDepositToAccount.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (!GUIForm.depositacc.isVisible()) { + GUIForm.depositacc.setVisible(true); + } else { + JOptionPane.showMessageDialog(getComponent(0), "Already Opened", "Warning", 0); + } + + } + }); + btnDepositToAccount.setBounds(120, 200, 200, 40); + contentPane.add(btnDepositToAccount); + + JButton btnWithdrawFromAccount = new JButton("Withdraw"); + btnWithdrawFromAccount.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (!GUIForm.withdraw.isVisible()) { + GUIForm.withdraw.setVisible(true); + } else { + JOptionPane.showMessageDialog(getComponent(0), "Already Opened", "Warning", 0); + } - /** - * - */ - private static final long serialVersionUID = 1L; - private JPanel contentPane; - - /** - * Create the frame. - */ - public Menu() { - setTitle("Banking System"); - setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE); - setBounds(100, 100, 649, 474); - contentPane = new JPanel(); - contentPane.setBackground(SystemColor.activeCaption); - contentPane.setForeground(SystemColor.activeCaption); - contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); - setContentPane(contentPane); - contentPane.setLayout(null); - - - JLabel lblBankingSystem = new JLabel("Banking System"); - lblBankingSystem.setHorizontalAlignment(SwingConstants.CENTER); - lblBankingSystem.setFont(new Font("Tahoma", Font.BOLD, 24)); - lblBankingSystem.setBounds(0, 69, 613, 59); - contentPane.add(lblBankingSystem); - - FileIO.Read(); - -// JButton btnAddAccount = new JButton("Add Account"); -// btnAddAccount.addActionListener(new ActionListener() { -// public void actionPerformed(ActionEvent e) { -// if(!GUIForm.addaccount.isVisible()) -// { -// GUIForm.addaccount.setVisible(true); -// } -// else -// { -// JOptionPane.showMessageDialog(getComponent(0), "Already Opened", "Warning", 0); -// } -// -// } -// }); -// btnAddAccount.setBounds(217, 162, 194, 40); -// contentPane.add(btnAddAccount); - - JButton btnDepositToAccount = new JButton("Deposit To Account"); - btnDepositToAccount.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - if(!GUIForm.depositacc.isVisible()) - { - GUIForm.depositacc.setVisible(true); - } - else - { - JOptionPane.showMessageDialog(getComponent(0), "Already Opened", "Warning", 0); - } - - } - }); - btnDepositToAccount.setBounds(217, 213, 194, 33); - contentPane.add(btnDepositToAccount); - - JButton btnWithdrawFromAccount = new JButton("Withdraw From Account"); - btnWithdrawFromAccount.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - if(!GUIForm.withdraw.isVisible()) - { - GUIForm.withdraw.setVisible(true); - } - else - { - JOptionPane.showMessageDialog(getComponent(0), "Already Opened", "Warning", 0); - } - - - } - - }); - btnWithdrawFromAccount.setBounds(217, 256, 194, 33); - contentPane.add(btnWithdrawFromAccount); - - JButton btnDisplayAccountList = new JButton("Display Account List"); - btnDisplayAccountList.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - - if(!GUIForm.displaylist.isVisible()) - { - GUIForm.displaylist.setVisible(true); - } - else - { - JOptionPane.showMessageDialog(getComponent(0), "Already Opened", "Warning", 0); - } - - } - }); - btnDisplayAccountList.setBounds(217, 300, 194, 32); - contentPane.add(btnDisplayAccountList); - - JButton btnExit = new JButton("Exit"); - btnExit.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent arg0) { - JOptionPane.showMessageDialog(getComponent(0), "Thanks For Using") ; - FileIO.Write(); - System.exit(0); - } - }); - btnExit.setBounds(217, 343, 194, 33); - contentPane.add(btnExit); - - JButton btnNewButton = new JButton("Add Account"); - btnNewButton.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - if(!GUIForm.addaccount.isVisible()) - { - GUIForm.addaccount.setVisible(true); - } - else - { - JOptionPane.showMessageDialog(getComponent(0), "Already Opened", "Warning", 0); - } - - - } - - }); - btnNewButton.setBounds(217, 166, 194, 36); - contentPane.add(btnNewButton); - - JLabel lblNewLabel = new JLabel("New label"); - lblNewLabel.setIcon(new ImageIcon(Menu.class.getResource("/img/1.png"))); - lblNewLabel.setBounds(397, 166, 216, 213); - contentPane.add(lblNewLabel); - - //Image image=GenerateImage.toImage(true); //this generates an image file - ImageIcon icon = new ImageIcon("1.png"); - } + } + + }); + btnWithdrawFromAccount.setBounds(120, 260, 200, 40); + contentPane.add(btnWithdrawFromAccount); + + JButton btnDisplayAccountList = new JButton("Browse Accounts"); + btnDisplayAccountList.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + + if (!GUIForm.displaylist.isVisible()) { + GUIForm.displaylist.setVisible(true); + } else { + JOptionPane.showMessageDialog(getComponent(0), "Already Opened", "Warning", 0); + } + + } + }); + btnDisplayAccountList.setBounds(120, 320, 200, 40); + contentPane.add(btnDisplayAccountList); + + JButton btnTransfer = new JButton("Transfer Funds"); + btnTransfer.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (!GUIForm.transferFunds.isVisible()) { + GUIForm.transferFunds.setVisible(true); + } else { + JOptionPane.showMessageDialog(getComponent(0), "Already Opened", "Warning", 0); + } + } + }); + btnTransfer.setBounds(400, 140, 200, 40); + contentPane.add(btnTransfer); + + JButton btnTransactions = new JButton("Transaction History"); + btnTransactions.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (!GUIForm.transactionHistory.isVisible()) { + GUIForm.transactionHistory.setVisible(true); + } else { + JOptionPane.showMessageDialog(getComponent(0), "Already Opened", "Warning", 0); + } + } + }); + btnTransactions.setBounds(400, 200, 200, 40); + contentPane.add(btnTransactions); + + JButton btnInsights = new JButton("Insights Dashboard"); + btnInsights.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + if (!GUIForm.insightsDashboard.isVisible()) { + GUIForm.insightsDashboard.setVisible(true); + } else { + JOptionPane.showMessageDialog(getComponent(0), "Already Opened", "Warning", 0); + } + } + }); + btnInsights.setBounds(400, 260, 200, 40); + contentPane.add(btnInsights); + + JButton btnExit = new JButton("Exit & Save"); + btnExit.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent arg0) { + JOptionPane.showMessageDialog(getComponent(0), "Thanks For Using"); + FileIO.Write(); + System.exit(0); + } + }); + btnExit.setBounds(400, 320, 200, 40); + contentPane.add(btnExit); + } } + diff --git a/src/GUI/TransactionHistory.java b/src/GUI/TransactionHistory.java new file mode 100644 index 0000000..e6be451 --- /dev/null +++ b/src/GUI/TransactionHistory.java @@ -0,0 +1,162 @@ +package GUI; + +import java.awt.Font; +import java.awt.SystemColor; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.util.List; +import java.util.stream.Collectors; + +import javax.swing.JButton; +import javax.swing.JComboBox; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JTable; +import javax.swing.JTextField; +import javax.swing.SwingConstants; +import javax.swing.border.EmptyBorder; +import javax.swing.table.DefaultTableModel; + +import Bank.BankAccount; +import Bank.Transaction; +import Bank.TransactionType; +import Data.FileIO; +import Exceptions.AccNotFound; + +public class TransactionHistory extends JFrame { + + private static final long serialVersionUID = 1L; + private JPanel contentPane; + private JTextField accountField; + private JTable table; + private DefaultTableModel tableModel; + private JLabel balanceLabel; + private JComboBox typeFilter; + + public TransactionHistory() { + setTitle("Transaction History"); + setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + setBounds(100, 100, 720, 520); + contentPane = new JPanel(); + contentPane.setBackground(SystemColor.activeCaption); + contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); + setContentPane(contentPane); + contentPane.setLayout(null); + + JLabel title = new JLabel("Transaction History"); + title.setHorizontalAlignment(SwingConstants.CENTER); + title.setFont(new Font("Tahoma", Font.BOLD, 20)); + title.setBounds(10, 11, 684, 31); + contentPane.add(title); + + JLabel accountLabel = new JLabel("Account Number:"); + accountLabel.setHorizontalAlignment(SwingConstants.RIGHT); + accountLabel.setBounds(20, 60, 120, 25); + contentPane.add(accountLabel); + + accountField = new JTextField(); + accountField.setBounds(150, 60, 200, 25); + contentPane.add(accountField); + + typeFilter = new JComboBox<>(new String[] { "All", "Deposit", "Withdrawal", "Transfer In", + "Transfer Out", "Interest", "Fee" }); + typeFilter.setBounds(360, 60, 150, 25); + contentPane.add(typeFilter); + + JButton btnLoad = new JButton("Load History"); + btnLoad.setBounds(520, 60, 140, 25); + btnLoad.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + loadHistory(); + } + }); + contentPane.add(btnLoad); + + tableModel = new DefaultTableModel(new Object[] { "Date", "Type", "Amount", "Balance", "Note" }, 0) { + private static final long serialVersionUID = 1L; + + @Override + public boolean isCellEditable(int row, int column) { + return false; + } + }; + table = new JTable(tableModel); + table.setFont(new Font("Tahoma", Font.PLAIN, 12)); + table.getTableHeader().setFont(new Font("Tahoma", Font.BOLD, 12)); + + JScrollPane scrollPane = new JScrollPane(table); + scrollPane.setBounds(20, 110, 664, 330); + contentPane.add(scrollPane); + + balanceLabel = new JLabel("Balance: "); + balanceLabel.setHorizontalAlignment(SwingConstants.RIGHT); + balanceLabel.setFont(new Font("Tahoma", Font.BOLD, 12)); + balanceLabel.setBounds(20, 452, 664, 25); + contentPane.add(balanceLabel); + } + + private void loadHistory() { + try { + String accountNumber = accountField.getText().trim(); + if (accountNumber.isEmpty()) { + JOptionPane.showMessageDialog(getComponent(0), + "Please enter an account number to load history"); + return; + } + + BankAccount account = FileIO.bank.findAccount(accountNumber); + if (account == null) { + throw new AccNotFound("Account not found"); + } + + List transactions = account.getTransactions(); + String filter = (String) typeFilter.getSelectedItem(); + if (!"All".equals(filter)) { + TransactionType type = mapFilterToType(filter); + transactions = transactions.stream().filter(t -> t.getType() == type) + .collect(Collectors.toList()); + } + + tableModel.setRowCount(0); + for (Transaction transaction : transactions) { + tableModel.addRow(new Object[] { transaction.getFormattedTimestamp(), + formatType(transaction.getType()), + String.format("%.2f", transaction.getAmount()), + String.format("%.2f", transaction.getBalanceAfter()), + transaction.getDescription() }); + } + + balanceLabel.setText(String.format("Balance: %.2f", account.getbalance())); + } catch (AccNotFound ex) { + JOptionPane.showMessageDialog(getComponent(0), ex.getMessage()); + } + } + + private TransactionType mapFilterToType(String filter) { + switch (filter) { + case "Deposit": + return TransactionType.DEPOSIT; + case "Withdrawal": + return TransactionType.WITHDRAWAL; + case "Transfer In": + return TransactionType.TRANSFER_IN; + case "Transfer Out": + return TransactionType.TRANSFER_OUT; + case "Interest": + return TransactionType.INTEREST; + case "Fee": + return TransactionType.FEE; + default: + return TransactionType.DEPOSIT; + } + } + + private String formatType(TransactionType type) { + String raw = type.name().toLowerCase().replace('_', ' '); + return Character.toUpperCase(raw.charAt(0)) + raw.substring(1); + } +} + diff --git a/src/GUI/TransferFunds.java b/src/GUI/TransferFunds.java new file mode 100644 index 0000000..e2755f4 --- /dev/null +++ b/src/GUI/TransferFunds.java @@ -0,0 +1,143 @@ +package GUI; + +import java.awt.Font; +import java.awt.SystemColor; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.JButton; +import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.SwingConstants; +import javax.swing.border.EmptyBorder; + +import Data.FileIO; +import Exceptions.AccNotFound; +import Exceptions.InvalidAmount; +import Exceptions.MaxBalance; +import Exceptions.MaxWithdraw; + +public class TransferFunds extends JFrame { + + private static final long serialVersionUID = 1L; + private JPanel contentPane; + private JTextField fromField; + private JTextField toField; + private JTextField amountField; + private JTextField noteField; + + public TransferFunds() { + setTitle("Transfer Funds"); + setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + setBounds(100, 100, 520, 360); + contentPane = new JPanel(); + contentPane.setBackground(SystemColor.activeCaption); + contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); + setContentPane(contentPane); + contentPane.setLayout(null); + + JLabel title = new JLabel("Transfer Funds Between Accounts"); + title.setHorizontalAlignment(SwingConstants.CENTER); + title.setFont(new Font("Tahoma", Font.BOLD, 18)); + title.setBounds(10, 11, 484, 36); + contentPane.add(title); + + JLabel fromLabel = new JLabel("From Account:"); + fromLabel.setHorizontalAlignment(SwingConstants.RIGHT); + fromLabel.setBounds(20, 78, 126, 20); + contentPane.add(fromLabel); + + fromField = new JTextField(); + fromField.setBounds(156, 78, 268, 20); + contentPane.add(fromField); + + JLabel toLabel = new JLabel("To Account:"); + toLabel.setHorizontalAlignment(SwingConstants.RIGHT); + toLabel.setBounds(20, 118, 126, 20); + contentPane.add(toLabel); + + toField = new JTextField(); + toField.setBounds(156, 118, 268, 20); + contentPane.add(toField); + + JLabel amountLabel = new JLabel("Amount:"); + amountLabel.setHorizontalAlignment(SwingConstants.RIGHT); + amountLabel.setBounds(20, 158, 126, 20); + contentPane.add(amountLabel); + + amountField = new JTextField(); + amountField.setBounds(156, 158, 268, 20); + contentPane.add(amountField); + + JLabel noteLabel = new JLabel("Note:"); + noteLabel.setHorizontalAlignment(SwingConstants.RIGHT); + noteLabel.setBounds(20, 198, 126, 20); + contentPane.add(noteLabel); + + noteField = new JTextField(); + noteField.setBounds(156, 198, 268, 20); + contentPane.add(noteField); + + JButton btnTransfer = new JButton("Transfer"); + btnTransfer.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + try { + String from = fromField.getText().trim(); + String to = toField.getText().trim(); + double amount = Double.parseDouble(amountField.getText().trim()); + String note = noteField.getText().trim(); + + if (from.isEmpty() || to.isEmpty()) { + JOptionPane.showMessageDialog(getComponent(0), + "Please provide both source and destination accounts"); + return; + } + + int confirm = JOptionPane.showConfirmDialog(getComponent(0), + String.format("Transfer %.2f from %s to %s?", amount, from, to)); + if (confirm != 0) { + return; + } + + FileIO.bank.transfer(from, to, amount, note); + FileIO.Write(); + GUIForm.UpdateDisplay(); + + JOptionPane.showMessageDialog(getComponent(0), "Transfer successful"); + dispose(); + } catch (NumberFormatException ex) { + JOptionPane.showMessageDialog(getComponent(0), + "Please enter a valid numeric amount"); + } catch (InvalidAmount | MaxBalance | MaxWithdraw ex) { + JOptionPane.showMessageDialog(getComponent(0), ex.getMessage()); + } catch (AccNotFound ex) { + JOptionPane.showMessageDialog(getComponent(0), "One or more accounts not found"); + } finally { + clearFields(); + } + } + }); + btnTransfer.setBounds(110, 252, 120, 30); + contentPane.add(btnTransfer); + + JButton btnReset = new JButton("Reset"); + btnReset.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + clearFields(); + } + }); + btnReset.setBounds(280, 252, 120, 30); + contentPane.add(btnReset); + } + + private void clearFields() { + fromField.setText(null); + toField.setText(null); + amountField.setText(null); + noteField.setText(null); + } +} + diff --git a/src/GUI/WithdrawAcc.java b/src/GUI/WithdrawAcc.java index 8cf6b4f..f902976 100644 --- a/src/GUI/WithdrawAcc.java +++ b/src/GUI/WithdrawAcc.java @@ -1,152 +1,145 @@ package GUI; + +import java.awt.Font; +import java.awt.SystemColor; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; + +import javax.swing.JButton; import javax.swing.JFrame; +import javax.swing.JLabel; +import javax.swing.JOptionPane; import javax.swing.JPanel; +import javax.swing.JTextField; +import javax.swing.SwingConstants; import javax.swing.border.EmptyBorder; +import Data.FileIO; import Exceptions.AccNotFound; import Exceptions.InvalidAmount; import Exceptions.MaxBalance; import Exceptions.MaxWithdraw; -import javax.swing.JLabel; -import javax.swing.JOptionPane; -import javax.swing.SwingConstants; -import java.awt.Font; -import javax.swing.JTextField; -import javax.swing.JButton; -import java.awt.event.ActionListener; -import java.io.Serializable; -import java.awt.event.ActionEvent; -import Data.FileIO; -import java.awt.SystemColor; +public class WithdrawAcc extends JFrame { + + /** + * + */ + private static final long serialVersionUID = 1L; + private JPanel contentPane; + private JTextField accountField; + private JTextField amountField; + private JTextField noteField; + + public WithdrawAcc() { + setTitle("Withdraw From Account"); + setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + setBounds(100, 100, 480, 320); + contentPane = new JPanel(); + contentPane.setBackground(SystemColor.activeCaption); + contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); + setContentPane(contentPane); + contentPane.setLayout(null); + + JLabel lblWithdraw = new JLabel("Withdraw From Account"); + lblWithdraw.setFont(new Font("Tahoma", Font.BOLD, 16)); + lblWithdraw.setHorizontalAlignment(SwingConstants.CENTER); + lblWithdraw.setBounds(10, 11, 444, 36); + contentPane.add(lblWithdraw); + + JLabel lblName = new JLabel("Account Number:"); + lblName.setHorizontalAlignment(SwingConstants.RIGHT); + lblName.setBounds(10, 86, 126, 14); + contentPane.add(lblName); + + accountField = new JTextField(); + accountField.setBounds(146, 83, 258, 20); + contentPane.add(accountField); + accountField.setColumns(10); + + JLabel lblAmount = new JLabel("Amount:"); + lblAmount.setHorizontalAlignment(SwingConstants.RIGHT); + lblAmount.setBounds(10, 130, 126, 14); + contentPane.add(lblAmount); + + amountField = new JTextField(); + amountField.setColumns(10); + amountField.setBounds(146, 127, 258, 20); + contentPane.add(amountField); -public class WithdrawAcc extends JFrame implements Serializable { - - /** - * - */ - private static final long serialVersionUID = 1L; - private JPanel contentPane; - private JTextField textField; - private JTextField textField_1; - - - /** - * Create the frame. - */ - public WithdrawAcc() { - setTitle("Withdraw From Account"); - setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); - setBounds(100, 100, 450, 300); - contentPane = new JPanel(); - contentPane.setBackground(SystemColor.activeCaption); - contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); - setContentPane(contentPane); - contentPane.setLayout(null); - - JLabel lblDepositToAccount = new JLabel("Withdraw From Account"); - lblDepositToAccount.setFont(new Font("Tahoma", Font.BOLD, 16)); - lblDepositToAccount.setHorizontalAlignment(SwingConstants.CENTER); - lblDepositToAccount.setBounds(10, 11, 414, 36); - contentPane.add(lblDepositToAccount); - - JLabel lblName = new JLabel("Account Number:"); - lblName.setHorizontalAlignment(SwingConstants.RIGHT); - lblName.setBounds(0, 86, 106, 14); - contentPane.add(lblName); - - textField = new JTextField(); - textField.setBounds(116, 83, 216, 20); - contentPane.add(textField); - textField.setColumns(10); - - textField_1 = new JTextField(); - textField_1.setColumns(10); - textField_1.setBounds(116, 147, 216, 20); - contentPane.add(textField_1); - - JLabel lblAmount = new JLabel("Amount:"); - lblAmount.setHorizontalAlignment(SwingConstants.RIGHT); - lblAmount.setBounds(10, 150, 96, 14); - contentPane.add(lblAmount); - - JButton btnDeposit = new JButton("Withdraw"); - btnDeposit.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - - String aacountNum; - double amt; - aacountNum=textField.getText(); - amt=Double.parseDouble(textField_1.getText()); - try { - int a=JOptionPane.showConfirmDialog(getComponent(0), "Confirm?"); - if(a==0) - { - - FileIO.bank.withdraw(aacountNum, amt); - JOptionPane.showMessageDialog(getComponent(0),"Withdraw Successful"); - dispose(); - } - else - { - textField.setText(null); - textField_1.setText(null); - - } - - } catch (MaxBalance e1) { - JOptionPane.showMessageDialog(getComponent(0), "Insufficient Balance"); - JOptionPane.showMessageDialog(getComponent(0),"Failed"); - textField.setText(null); - textField_1.setText(null); - - } catch (AccNotFound e1) { - JOptionPane.showMessageDialog(getComponent(0), "Sorry! Account Not Found"); - JOptionPane.showMessageDialog(getComponent(0),"Failed"); - textField.setText(null); - textField_1.setText(null); - - } catch (MaxWithdraw e1) { - JOptionPane.showMessageDialog(getComponent(0), "Maximum Withdraw Limit Exceed"); - JOptionPane.showMessageDialog(getComponent(0),"Failed"); - textField.setText(null); - textField_1.setText(null); - - } catch (InvalidAmount e1) { - JOptionPane.showMessageDialog(getComponent(0), "Invalid Amount"); - JOptionPane.showMessageDialog(getComponent(0),"Failed"); - textField.setText(null); - textField_1.setText(null); - } - - - textField.setText(null); - textField_1.setText(null); - - - - - } - }); - btnDeposit.setBounds(73, 212, 89, 23); - contentPane.add(btnDeposit); - - JButton btnReset = new JButton("Reset"); - btnReset.setBounds(243, 212, 89, 23); - contentPane.add(btnReset); - btnReset.addActionListener(new ActionListener() { - public void actionPerformed(ActionEvent e) { - - textField.setText(null); - textField_1.setText(null); - } - }); - - - - - - - - } + JLabel lblNote = new JLabel("Description:"); + lblNote.setHorizontalAlignment(SwingConstants.RIGHT); + lblNote.setBounds(10, 174, 126, 14); + contentPane.add(lblNote); + + noteField = new JTextField(); + noteField.setColumns(10); + noteField.setBounds(146, 171, 258, 20); + contentPane.add(noteField); + + JButton btnWithdraw = new JButton("Withdraw"); + btnWithdraw.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + try { + String accountNumber = accountField.getText().trim(); + double amount = Double.parseDouble(amountField.getText().trim()); + String note = noteField.getText().trim(); + + if (accountNumber.isEmpty()) { + JOptionPane.showMessageDialog(getComponent(0), + "Please enter an account number"); + return; + } + + int confirm = JOptionPane.showConfirmDialog(getComponent(0), + "Withdraw " + amount + " from account " + accountNumber + "?"); + if (confirm != 0) { + return; + } + + FileIO.bank.withdraw(accountNumber, amount, + note.isEmpty() ? "Withdrawal" : note); + FileIO.Write(); + GUIForm.UpdateDisplay(); + + JOptionPane.showMessageDialog(getComponent(0), "Withdrawal Successful\nNew Balance: " + + String.format("%.2f", + FileIO.bank.findAccount(accountNumber) + .getbalance())); + dispose(); + } catch (NumberFormatException ex) { + JOptionPane.showMessageDialog(getComponent(0), + "Please enter a valid numeric amount"); + } catch (InvalidAmount ex) { + JOptionPane.showMessageDialog(getComponent(0), ex.getMessage()); + } catch (AccNotFound ex) { + JOptionPane.showMessageDialog(getComponent(0), "Account not found"); + } catch (MaxBalance ex) { + JOptionPane.showMessageDialog(getComponent(0), ex.getMessage()); + } catch (MaxWithdraw ex) { + JOptionPane.showMessageDialog(getComponent(0), ex.getMessage()); + } finally { + clearFields(); + } + } + }); + btnWithdraw.setBounds(86, 227, 110, 25); + contentPane.add(btnWithdraw); + + JButton btnReset = new JButton("Reset"); + btnReset.setBounds(266, 227, 110, 25); + btnReset.addActionListener(new ActionListener() { + public void actionPerformed(ActionEvent e) { + clearFields(); + } + }); + contentPane.add(btnReset); + } + + private void clearFields() { + accountField.setText(null); + amountField.setText(null); + noteField.setText(null); + } } +