diff --git a/src/main/java/me/zacharias/bank/Account.java b/src/main/java/me/zacharias/bank/Account.java index 89d0e17..07e9f84 100644 --- a/src/main/java/me/zacharias/bank/Account.java +++ b/src/main/java/me/zacharias/bank/Account.java @@ -7,20 +7,46 @@ import org.intellij.lang.annotations.MagicConstant; import java.util.ArrayList; import java.util.UUID; +/** + * Represents an account in the bank for a user. + */ public class Account { + /** + * List of transactions in the account.
+ * Each transaction contains information about the transaction, such as the amount, description, and the type of transaction. + */ ArrayList transactions; + /** + * Name of the account. + */ String name; + /** + * Balance of the account. + */ double balance; + /** + * ID of the account.
+ * Also works as the Account number. + */ UUID id; + /** + * Interest rate of the account. + */ @MagicConstant(valuesFromClass = Interests.class) double interestRate; - - public Account(String name, double balance, @MagicConstant(valuesFromClass = Interests.class) double interestRate) { + + /** + * Creates a new account. + * @param name Name of the account. + * @param interestRate Interest rate of the account. + */ + public Account(String name, @MagicConstant(valuesFromClass = Interests.class) double interestRate) { this.name = name; - this.balance = balance; + this.balance = 0; transactions = new ArrayList<>(); id = UUID.randomUUID(); this.interestRate = interestRate; + transactions.add(new Transaction(0, "Account opened", id, id, TransactionType.OPEN)); } public void WithdrawTransaction(double amount, String description, UUID destination) { @@ -62,7 +88,7 @@ public class Account { throw new IllegalArgumentException("Insufficient balance"); } balance -= transaction.getAmount(); - } else if(transaction.getType() == TransactionType.DEPOSIT) { + } else if(transaction.getType() == TransactionType.DEPOSIT || transaction.getType() == TransactionType.OPEN || transaction.getType() == TransactionType.CLOSE) { if(transaction.getAmount() < 0) { throw new IllegalArgumentException("Amount cannot be negative"); } @@ -92,7 +118,12 @@ public class Account { public double getInterest() { return balance * (1+interestRate); } - + + @Override + public String toString() { + return name + " - " + balance + " kr"; + } + public static class Interests { public static final double BANK_ACCOUNT_INTEREST_RATE = 0.001; diff --git a/src/main/java/me/zacharias/bank/BankAccount.java b/src/main/java/me/zacharias/bank/BankAccount.java index 8e63b24..f1a1361 100644 --- a/src/main/java/me/zacharias/bank/BankAccount.java +++ b/src/main/java/me/zacharias/bank/BankAccount.java @@ -6,7 +6,7 @@ import static me.zacharias.bank.Account.Interests.BANK_ACCOUNT_INTEREST_RATE; * This class only works as a way to have prefilled information, but can be replaced by just calling the {@link Account#Account(String, double, double)} instead */ public class BankAccount extends Account { - public BankAccount(String name, double balance) { - super(name, balance, BANK_ACCOUNT_INTEREST_RATE); + public BankAccount(String name) { + super(name, BANK_ACCOUNT_INTEREST_RATE); } } diff --git a/src/main/java/me/zacharias/bank/Main.java b/src/main/java/me/zacharias/bank/Main.java index a7c3a15..07fa7f4 100644 --- a/src/main/java/me/zacharias/bank/Main.java +++ b/src/main/java/me/zacharias/bank/Main.java @@ -12,25 +12,16 @@ import static me.zacharias.bank.Utils.*; public class Main { User user; - static Gson gson; - - static { - GsonBuilder gsonBuilder = new GsonBuilder(); - //gsonBuilder.registerTypeAdapter(Account.class, new AccountAdapter()); - - gson = gsonBuilder.create(); - } - public static void main(String[] args) { - String user = SHA256("zacharias"); + String user = SHA256("user"); File userFile = new File("./users/" + user + ".json"); if(!userFile.exists()) { - User u = new User("zacharias"); - u.createAccount("Konto", 0.0); + User u = new User("user"); + u.createAccount("Konto"); Account a = u.getAccount("Konto"); - a.DepositTransaction(104, "Spawnar pängar", UUID.randomUUID()); + a.DepositTransaction(104, "Deposit", UUID.randomUUID()); String json = gson.toJson(u); try { @@ -52,7 +43,7 @@ public class Main { //return; } - String name = "zacharias";//console.readLine("Enter your name: "); + String name = "user";//console.readLine("Enter your name: "); String userHash = SHA256(name); diff --git a/src/main/java/me/zacharias/bank/SavingsAccount.java b/src/main/java/me/zacharias/bank/SavingsAccount.java index 3f3b893..284d278 100644 --- a/src/main/java/me/zacharias/bank/SavingsAccount.java +++ b/src/main/java/me/zacharias/bank/SavingsAccount.java @@ -7,7 +7,7 @@ import static me.zacharias.bank.Account.Interests.SAVINGS_ACCOUNT_INTEREST_RATE; */ public class SavingsAccount extends Account{ - public SavingsAccount(String name, double balance) { - super(name, balance, SAVINGS_ACCOUNT_INTEREST_RATE); + public SavingsAccount(String name) { + super(name, SAVINGS_ACCOUNT_INTEREST_RATE); } } diff --git a/src/main/java/me/zacharias/bank/User.java b/src/main/java/me/zacharias/bank/User.java index 935a538..bef7376 100644 --- a/src/main/java/me/zacharias/bank/User.java +++ b/src/main/java/me/zacharias/bank/User.java @@ -1,5 +1,9 @@ package me.zacharias.bank; +import me.zacharias.bank.transaction.Transaction; +import me.zacharias.bank.transaction.TransactionType; +import org.jetbrains.annotations.NotNull; + import java.util.ArrayList; import java.util.UUID; @@ -14,14 +18,16 @@ public class User { accounts = new ArrayList<>(); } - public void createAccount(String name, double balance) { - Account account = new BankAccount(name, balance); + public UUID createAccount(String name) { + Account account = new BankAccount(name); accounts.add(account); + return account.getId(); } - public void createSavingsAccount(String name, double balance) { - Account account = new SavingsAccount(name, balance); + public UUID createSavingsAccount(String name) { + Account account = new SavingsAccount(name); accounts.add(account); + return account.getId(); } public Account getAccount(String name) { @@ -33,7 +39,7 @@ public class User { return null; } - public Account getAccount(UUID id) { + public Account getAccount(@NotNull UUID id) { for (Account account : accounts) { if (account.id.equals(id)) { return account; @@ -42,17 +48,25 @@ public class User { return null; } - public void deleteAccount(Account account) { + public void deleteAccount(@NotNull Account account) { Account base = null; for(Account a : accounts) { - if(a instanceof BankAccount) { + if(a.getId().equals(account.getId())) { base = a; } } if(base == null) { - throw new IllegalArgumentException("No bank accounts found"); + throw new IllegalArgumentException("No other bank accounts found"); } - base.TransferTransaction(account.getBalance(), "Account closed", account.getId(), base.getId()); + base.handleTransaction(new Transaction(account.getBalance(), "Account closed", account.getId(), base.getId(), TransactionType.CLOSE)); accounts.remove(account); } + + public String getName() { + return name; + } + + public ArrayList getAccounts() { + return accounts; + } } diff --git a/src/main/java/me/zacharias/bank/Utils.java b/src/main/java/me/zacharias/bank/Utils.java index 1fd1a6e..ceabebf 100644 --- a/src/main/java/me/zacharias/bank/Utils.java +++ b/src/main/java/me/zacharias/bank/Utils.java @@ -1,5 +1,8 @@ package me.zacharias.bank; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; + import javax.crypto.Cipher; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; @@ -14,6 +17,22 @@ import java.security.SecureRandom; import java.util.Base64; public class Utils { + + public static final Gson gson; + + static { + GsonBuilder gsonBuilder = new GsonBuilder(); + //gsonBuilder.registerTypeAdapter(Account.class, new AccountAdapter()); + + gson = gsonBuilder.create(); + + File users = new File("./users"); + + if(!users.exists()) { + users.mkdir(); + } + } + public static String SHA256(String input) { MessageDigest sha256 = null; try { diff --git a/src/main/java/me/zacharias/bank/app/AccountView.java b/src/main/java/me/zacharias/bank/app/AccountView.java new file mode 100644 index 0000000..e1ce2fc --- /dev/null +++ b/src/main/java/me/zacharias/bank/app/AccountView.java @@ -0,0 +1,67 @@ +package me.zacharias.bank.app; + +import me.zacharias.bank.Account; +import me.zacharias.bank.transaction.Transaction; + +import javax.swing.*; +import java.awt.*; + +public class AccountView extends JPanel { + + Main bankApplication; + Account account; + + JLabel accountName; + JLabel balance; + JLabel AccountNumber; + JList transactionList; + + public AccountView(Main bankApplication, Account account) { + this.bankApplication = bankApplication; + this.account = account; + + this.setLayout(null); + + accountName = new JLabel(account.getName()); + accountName.setBounds(10, 10, 200, 30); + + balance = new JLabel(account.getBalance() + " kr"); + balance.setBounds(10, 50, 200, 30); + + AccountNumber = new JLabel(account.getId().toString()); + AccountNumber.setBounds(10, 90, 200, 30); + + transactionList = new JList<>(); + transactionList.setBounds(10, 130, 200, 30); + transactionList.setModel(new DefaultListModel<>()); + transactionList.setBackground(Color.GRAY); + transactionList.setCellRenderer(new ListCellRenderer() { + @Override + public Component getListCellRendererComponent(JList list, Transaction value, int index, boolean isSelected, boolean cellHasFocus) { + JButton label = new JButton(); + label.setText(value.getDescription() + " " + value.getAmount() + " kr"); + label.setBackground(Color.GRAY); + label.addActionListener(e -> { + bankApplication.showAccount(account); + }); + return label; + } + }); + + this.add(accountName); + this.add(balance); + this.add(AccountNumber); + this.add(transactionList); + } + + @Override + protected void paintComponent(Graphics g) { + accountName.setBounds(10, 10, 200, 30); + balance.setBounds(10, 50, 200, 30); + AccountNumber.setBounds(10, 90, 200, 30); + transactionList.setBounds(10, 130, 200, 30); + + transactionList.setListData(account.getTransactions().toArray(new Transaction[0])); + super.paintComponent(g); + } +} diff --git a/src/main/java/me/zacharias/bank/app/Login.java b/src/main/java/me/zacharias/bank/app/Login.java new file mode 100644 index 0000000..bfd468b --- /dev/null +++ b/src/main/java/me/zacharias/bank/app/Login.java @@ -0,0 +1,135 @@ +package me.zacharias.bank.app; + +import me.zacharias.bank.User; +import me.zacharias.bank.Utils; + +import javax.swing.*; +import java.awt.*; +import java.awt.event.FocusEvent; +import java.awt.event.FocusListener; +import java.io.File; + +public class Login extends JPanel { + + //String username; + //String password; + User user = null; + + JTextField usernameField; + JLabel usernameLabel; + JPasswordField passwordField; + JLabel passwordLabel; + JLabel error; + JButton loginButton; + + Main bankApplication; + + public Login(Main bankApplication) { + this.bankApplication = bankApplication; + + this.setLayout(null); + + usernameField = new JTextField(); + usernameField.setBounds(getWidth()/2-100, 10, 200, 30); + usernameField.addFocusListener(new FocusListener() { + @Override + public void focusGained(FocusEvent e) { + usernameField.selectAll(); + } + + @Override + public void focusLost(FocusEvent e) { + usernameField.select(0, 0); + } + }); + + usernameLabel = new JLabel("Username"); + usernameLabel.setBounds(getWidth()/2-100-80, 10, 80, 30); + + passwordField = new JPasswordField(); + passwordField.setBounds(getWidth()/2-100, 50, 200, 30); + passwordField.addFocusListener(new FocusListener() { + @Override + public void focusGained(FocusEvent e) { + usernameField.selectAll(); + } + + @Override + public void focusLost(FocusEvent e) { + usernameField.select(0, 0); + } + }); + + passwordLabel = new JLabel("Password"); + passwordLabel.setBounds(getWidth()/2-100-80, 50, 80, 30); + + error = new JLabel(); + error.setBounds(getWidth()/2-100, 80, 200, 10); + error.setFont(new Font("Arial", Font.BOLD, 10)); + error.setForeground(Color.RED); + + loginButton = new JButton("Login"); + loginButton.setBounds(getWidth()/2-100, 95, 200, 30); + loginButton.addActionListener(e -> { + String username = usernameField.getText(); + String userHash = Utils.SHA256(username); + String password = new String(passwordField.getPassword()); + + File userFile = new File("users/" + userHash + ".json"); + if (!userFile.exists()) { + //JOptionPane.showMessageDialog(null, "Wrong username or password"); + error.setText("Wrong username or password"); + return; + } + + String userData; + try { + userData = Utils.Decrypt(Utils.ReadFile(userFile), password); + } catch (Exception ex) { + //JOptionPane.showMessageDialog(null, "Wrong username or password"); + error.setText("Wrong username or password"); + return; + } + + try{ + user = Utils.gson.fromJson(userData, User.class); + }catch (Exception ex){ + //JOptionPane.showMessageDialog(null, "Wrong username or password"); + error.setText("Wrong username or password"); + return; + } + + error.setText(""); + + bankApplication.login(user); + }); + + this.add(usernameField); + this.add(usernameLabel); + this.add(passwordField); + this.add(passwordLabel); + this.add(error); + this.add(loginButton); + } + + public User getUser() { + return user; + } + + @Override + protected void paintComponent(Graphics g) { + usernameField.setBounds(getWidth()/2-100, 10, 200, 30); + usernameLabel.setBounds(getWidth()/2-100-80, 10, 80, 30); + passwordField.setBounds(getWidth()/2-100, 50, 200, 30); + passwordLabel.setBounds(getWidth()/2-100-80, 50, 80, 30); + error.setBounds(getWidth()/2-100, 80, 200, 10); + loginButton.setBounds(getWidth()/2-100, 95, 200, 30); + super.paintComponent(g); + } + + public void clear() { + usernameField.setText(""); + passwordField.setText(""); + error.setText(""); + } +} diff --git a/src/main/java/me/zacharias/bank/app/Main.java b/src/main/java/me/zacharias/bank/app/Main.java new file mode 100644 index 0000000..87a6b4e --- /dev/null +++ b/src/main/java/me/zacharias/bank/app/Main.java @@ -0,0 +1,57 @@ +package me.zacharias.bank.app; + +import me.zacharias.bank.Account; +import me.zacharias.bank.User; + +import javax.swing.*; +import java.awt.*; + +public class Main extends JPanel { + public static void main(String[] args) { + new Main(); + } + + JFrame frame; + Login login; + MainMenu mainManu; + AccountView accountView; + + Timer timer = new Timer(100, e -> {frame.repaint();}); + + + public Main() { + frame = new JFrame("Bank"); + frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + frame.setSize(800, 600); + frame.setLocationRelativeTo(null); + + login = new Login(this); + login.setBounds(0, 0, 800, 600); + + frame.add(login); + + frame.setVisible(true); + timer.start(); + } + + public void login(User user) { + frame.remove(login); + mainManu = new MainMenu(user, this); + frame.add(mainManu); + frame.setVisible(true); + } + + public void logout() { + frame.remove(mainManu); + login.clear(); + frame.add(login); + frame.setVisible(true); + } + + public void showAccount(Account account) { + frame.remove(mainManu); + accountView = new AccountView(this, account); + frame.add(accountView); + frame.setVisible(true); + } +} diff --git a/src/main/java/me/zacharias/bank/app/MainMenu.java b/src/main/java/me/zacharias/bank/app/MainMenu.java new file mode 100644 index 0000000..43593de --- /dev/null +++ b/src/main/java/me/zacharias/bank/app/MainMenu.java @@ -0,0 +1,66 @@ +package me.zacharias.bank.app; + +import me.zacharias.bank.Account; +import me.zacharias.bank.User; + +import javax.swing.*; +import java.awt.*; + +public class MainMenu extends JPanel { + + User user; + Main bankApplication; + + JLabel welcome; + JButton logout; + + JList accountList; + + public MainMenu(User user, Main bankApplication) { + this.user = user; + this.bankApplication = bankApplication; + + this.setLayout(null); + + welcome = new JLabel("Welcome " + user.getName()); + welcome.setBounds(getWidth()/2-100, 10, 200, 30); + + logout = new JButton("Logout"); + logout.setBounds(getWidth()/2-100, getHeight()-50, 200, 30); + logout.addActionListener(e -> { + bankApplication.logout(); + }); + + accountList = new JList<>(); + accountList.setBounds(getWidth()/2-100, 80, 200, 30); + accountList.setModel(new DefaultListModel<>()); + accountList.setBackground(Color.GRAY); + accountList.setCellRenderer(new ListCellRenderer() { + @Override + public Component getListCellRendererComponent(JList list, Account value, int index, boolean isSelected, boolean cellHasFocus) { + JButton label = new JButton(); + label.setText(value.getName() + " " + value.getBalance() + " kr"); + label.setBackground(Color.GRAY); + label.addActionListener(e -> { + bankApplication.showAccount(value); + }); + return label; + } + }); + + this.add(welcome); + this.add(logout); + this.add(accountList); + } + + @Override + protected void paintComponent(Graphics g) { + welcome.setBounds(getWidth()/2-100, 10, 200, 30); + logout.setBounds(getWidth()/2-100, getHeight()-50, 200, 30); + accountList.setBounds(getWidth()/2-100, 80, 200, 30); + + + accountList.setListData(user.getAccounts().toArray(new Account[0])); + super.paintComponent(g); + } +} diff --git a/src/main/java/me/zacharias/bank/transaction/TransactionType.java b/src/main/java/me/zacharias/bank/transaction/TransactionType.java index 720a58f..0496a1b 100644 --- a/src/main/java/me/zacharias/bank/transaction/TransactionType.java +++ b/src/main/java/me/zacharias/bank/transaction/TransactionType.java @@ -1,5 +1,5 @@ package me.zacharias.bank.transaction; public enum TransactionType { - WITHDRAW, DEPOSIT, TRANSFER + WITHDRAW, DEPOSIT, OPEN, TRANSFER, CLOSE }