diff --git a/src/Main.java b/src/Main.java deleted file mode 100644 index e456075..0000000 --- a/src/Main.java +++ /dev/null @@ -1,19 +0,0 @@ -import me.teridax.jcash.gui.login.LoginView; - -import javax.swing.*; - -public class Main { - - public static void main(String[] args) { - SwingUtilities.invokeLater(() -> { - // Loader.load(); - - var window = new JFrame(); - window.setTitle("Bankautomat"); - window.setLocationByPlatform(true); - window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); - window.add(new LoginView()); - window.setVisible(true); - }); - } -} \ No newline at end of file diff --git a/src/me/teridax/jcash/Main.java b/src/me/teridax/jcash/Main.java new file mode 100644 index 0000000..7616d32 --- /dev/null +++ b/src/me/teridax/jcash/Main.java @@ -0,0 +1,61 @@ +package me.teridax.jcash; + +import me.teridax.jcash.gui.Loader; +import me.teridax.jcash.gui.account.AccountController; +import me.teridax.jcash.gui.login.LoginController; + +import javax.swing.*; + +public class Main { + + private static Main instance; + + private final JFrame window; + + private Main() { + window = new JFrame(); + window.setTitle("Bankautomat"); + window.setLocationByPlatform(true); + window.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); + } + + public static void main(String[] args) { + instance(); + getInstance().popLoginScreen(); + } + + public static Main getInstance() { + return instance; + } + + public static void instance() { + if (instance == null) { + instance = new Main(); + return; + } + + throw new IllegalStateException("me.teridax.jcash.Main is already initialized"); + } + + public void popLoginScreen() { + SwingUtilities.invokeLater(() -> { + var path = Loader.load(); + var login = new LoginController(path); + + login.addAccountSelectionListener(account -> { + var profileCont = new AccountController(account); + window.setContentPane(profileCont.getView()); + window.pack(); + }); + + window.setContentPane(login.getView()); + window.pack(); + window.setVisible(true); + }); + } + + public void logout() { + window.setContentPane(new JLabel("you're logged out")); + window.setVisible(false); + } +} \ No newline at end of file diff --git a/src/me/teridax/jcash/banking/Account.java b/src/me/teridax/jcash/banking/Account.java index 7ef9445..961178c 100644 --- a/src/me/teridax/jcash/banking/Account.java +++ b/src/me/teridax/jcash/banking/Account.java @@ -64,4 +64,8 @@ public abstract class Account { return false; } + + public String getDescription() { + return String.format("%s (%s)", iban, getClass().getSimpleName()); + } } diff --git a/src/me/teridax/jcash/banking/Bank.java b/src/me/teridax/jcash/banking/Bank.java index 41fd5d6..87a2af2 100644 --- a/src/me/teridax/jcash/banking/Bank.java +++ b/src/me/teridax/jcash/banking/Bank.java @@ -57,11 +57,11 @@ public final class Bank { return blz; } - public Optional getAccount(int iban) { + public Optional getAccount(int iban) { for (var owner : this.accounts.entrySet()) { for (var account : owner.getValue()) { if (account.getIban() == iban) { - return Optional.of(account); + return Optional.of(new Profile(owner.getKey(), this, account, getAccountsOfOwner(owner.getKey()))); } } } diff --git a/src/me/teridax/jcash/banking/BankingManagementSystem.java b/src/me/teridax/jcash/banking/BankingManagementSystem.java index c296c18..b09d361 100644 --- a/src/me/teridax/jcash/banking/BankingManagementSystem.java +++ b/src/me/teridax/jcash/banking/BankingManagementSystem.java @@ -56,6 +56,6 @@ public final class BankingManagementSystem { } public Optional getBank(String blz) { - return this.banks.stream().filter(b -> b.getBlz().equals(blz)).findFirst(); + return this.banks.stream().filter(b -> !b.getBlz().equals(blz)).findFirst(); } } diff --git a/src/me/teridax/jcash/banking/Profile.java b/src/me/teridax/jcash/banking/Profile.java new file mode 100644 index 0000000..9ac33a6 --- /dev/null +++ b/src/me/teridax/jcash/banking/Profile.java @@ -0,0 +1,41 @@ +package me.teridax.jcash.banking; + +public class Profile { + + private Owner owner; + private Bank bank; + private Account primaryAccount; + private Account[] accounts; + + public Profile(Owner owner, Bank bank, Account account, Account[] accounts) { + this.owner = owner; + this.bank = bank; + this.accounts = accounts; + this.primaryAccount = account; + } + + public Account getPrimaryAccount() { + return primaryAccount; + } + + public Owner getOwner() { + return owner; + } + + public Bank getBank() { + return bank; + } + + public Account[] getAccounts() { + return accounts; + } + + public void setPrimaryAccount(String description) { + for (Account account : accounts) { + if (account.getDescription().equals(description)) { + this.primaryAccount = account; + break; + } + } + } +} diff --git a/src/me/teridax/jcash/decode/Decoder.java b/src/me/teridax/jcash/decode/Decoder.java index 4af70b8..4be4189 100644 --- a/src/me/teridax/jcash/decode/Decoder.java +++ b/src/me/teridax/jcash/decode/Decoder.java @@ -13,7 +13,7 @@ import static junit.framework.TestCase.assertEquals; public class Decoder { private static final Locale LOCALE = Locale.GERMANY; - private static final NumberFormat LOCAL_NUMBER_FORMAT = NumberFormat.getInstance(LOCALE); + public static final NumberFormat LOCAL_NUMBER_FORMAT = NumberFormat.getInstance(LOCALE); public static double decodePercent(String number) throws IllegalArgumentException, NullPointerException { Objects.requireNonNull(number); diff --git a/src/me/teridax/jcash/gui/Loader.java b/src/me/teridax/jcash/gui/Loader.java index 4219c0b..28a9d15 100644 --- a/src/me/teridax/jcash/gui/Loader.java +++ b/src/me/teridax/jcash/gui/Loader.java @@ -4,6 +4,7 @@ import me.teridax.jcash.banking.BankingManagementSystem; import javax.swing.*; import javax.swing.filechooser.FileNameExtensionFilter; +import java.io.File; public class Loader { @@ -16,6 +17,7 @@ public class Loader { fileChooser.setFileFilter(FILE_FILTER); fileChooser.setDialogType(JFileChooser.OPEN_DIALOG); fileChooser.setAcceptAllFileFilterUsed(false); + fileChooser.setCurrentDirectory(new File("/home/teridax/IdeaProjects/JCash/res")); if (fileChooser.showDialog(null, "Load database") == JFileChooser.APPROVE_OPTION) { try { diff --git a/src/me/teridax/jcash/gui/account/AccountController.java b/src/me/teridax/jcash/gui/account/AccountController.java new file mode 100644 index 0000000..6a5227a --- /dev/null +++ b/src/me/teridax/jcash/gui/account/AccountController.java @@ -0,0 +1,33 @@ +package me.teridax.jcash.gui.account; + +import me.teridax.jcash.Main; +import me.teridax.jcash.banking.Profile; + +public class AccountController { + + private final AccountView view; + + public AccountController(Profile profile) { + this.view = new AccountView(); + this.view.setProfile(profile); + + createListeners(profile); + } + + private void createListeners(Profile profile) { + this.view.getAccountSelection().addActionListener(e -> { + var description = ((String) this.view.getAccountSelection().getSelectedItem()); + profile.setPrimaryAccount(description); + this.view.setProfile(profile); + }); + + this.view.getLogout().addActionListener(e -> { + Main.getInstance().logout(); + Main.getInstance().popLoginScreen(); + }); + } + + public AccountView getView() { + return view; + } +} diff --git a/src/me/teridax/jcash/gui/account/AccountView.java b/src/me/teridax/jcash/gui/account/AccountView.java new file mode 100644 index 0000000..4f1364d --- /dev/null +++ b/src/me/teridax/jcash/gui/account/AccountView.java @@ -0,0 +1,169 @@ +package me.teridax.jcash.gui.account; + +import me.teridax.jcash.banking.*; +import me.teridax.jcash.decode.Decoder; + +import javax.swing.*; +import java.awt.*; + +public class AccountView extends JPanel { + + private JTextField iban; + private JTextField name; + private JTextField address; + private JTextField bankName; + private JTextField blz; + private JTextField type; + private JTextField typeSpecialProperty; + private JTextField balance; + + private JLabel typeSpecialLabel; + + private JComboBox accountSelection; + + private JPanel content; + private JPanel buttonPanel; + + private JButton logout; + private JButton transfer; + private JButton deposit; + private JButton takeoff; + + public AccountView() { + createComponents(); + createLayout(); + + setBorder(BorderFactory.createEmptyBorder(8,8,8,8)); + } + + public void setProfile(Profile profile) { + var bank = profile.getBank(); + var account = profile.getPrimaryAccount(); + var owner = profile.getOwner(); + + this.blz.setText(bank.getBlz()); + this.bankName.setText(bank.getName()); + + this.iban.setText(String.valueOf(account.getIban())); + this.name.setText(owner.getName() + " " + owner.getFamilyName()); + this.address.setText(owner.getStreet() + " " + owner.getCity()); + + this.balance.setText(Decoder.LOCAL_NUMBER_FORMAT.format(account.getBalance()) + " €"); + + this.type.setText(account.getClass().getSimpleName()); + if (account instanceof Girokonto) { + this.typeSpecialLabel.setText("Überziehungsbetrag"); + this.typeSpecialProperty.setText( Decoder.LOCAL_NUMBER_FORMAT.format(((Girokonto) account).getOverdraft()) + " €"); + } else if (account instanceof SavingsAccount) { + this.typeSpecialLabel.setText("Zinsbetrag"); + this.typeSpecialProperty.setText( ((SavingsAccount) account).getInterest() + " %" ); + } + + this.accountSelection.removeAllItems(); + + for (var otherAccount : profile.getAccounts()) { + this.accountSelection.addItem(otherAccount.getDescription()); + } + this.accountSelection.setSelectedItem(account.getDescription()); + } + + private void createLayout() { + setLayout(new BorderLayout(16, 16)); + add(new JScrollPane(content), BorderLayout.CENTER); + add(buttonPanel, BorderLayout.SOUTH); + + content.setLayout(new GridBagLayout()); + var constraints = new GridBagConstraints(); + + constraints.gridwidth = 4; + constraints.insets = new Insets(12,12,12,12); + + var accountSelectionPanel = new JPanel(new BorderLayout(12, 0)); + accountSelectionPanel.add(iban, BorderLayout.CENTER); + accountSelectionPanel.add(accountSelection, BorderLayout.EAST); + + addInputRow(constraints, content, accountSelectionPanel, 1, new JLabel("Kontonummer", SwingConstants.RIGHT)); + addInputRow(constraints, content, name, 2, new JLabel("Vorname/Nachname", SwingConstants.RIGHT)); + addInputRow(constraints, content, address, 3, new JLabel("Adresse", SwingConstants.RIGHT)); + addInputRow(constraints, content, bankName, 4, new JLabel("Bank", SwingConstants.RIGHT)); + addInputRow(constraints, content, blz, 5, new JLabel("BLZ", SwingConstants.RIGHT)); + addInputRow(constraints, content, type, 6, new JLabel("Konto", SwingConstants.RIGHT)); + addInputRow(constraints, content, typeSpecialProperty, 7, typeSpecialLabel); + addInputRow(constraints, content, balance, 8, new JLabel("Kontostand", SwingConstants.RIGHT)); + + var buttonRightPanel = new JPanel(); + buttonRightPanel.add(transfer); + buttonRightPanel.add(deposit); + buttonRightPanel.add(takeoff); + + buttonPanel.add(logout, BorderLayout.LINE_START); + buttonPanel.add(buttonRightPanel, BorderLayout.LINE_END); + } + + private void createComponents() { + this.blz = new JTextField(); + this.iban = new JTextField(); + this.address = new JTextField(); + this.bankName = new JTextField(); + this.name = new JTextField(); + this.type = new JTextField(); + this.balance = new JTextField(); + this.typeSpecialProperty = new JTextField(); + + this.blz.setEditable(false); + this.iban.setEditable(false); + this.address.setEditable(false); + this.bankName.setEditable(false); + this.name.setEditable(false); + this.type.setEditable(false); + this.balance.setEditable(false); + this.typeSpecialProperty.setEditable(false); + + this.typeSpecialLabel = new JLabel("", SwingConstants.RIGHT); + + this.accountSelection = new JComboBox<>(); + + this.content = new JPanel(); + this.buttonPanel = new JPanel(new BorderLayout()); + + this.logout = new JButton("Abmelden"); + this.transfer = new JButton("Überweisen"); + this.deposit = new JButton("Einzahlen"); + this.takeoff = new JButton("Abheben"); + } + + private void addInputRow(GridBagConstraints constraints, JComponent target, JComponent comp, int row, JLabel label) { + constraints.gridwidth = 1; + constraints.gridx = 1; + constraints.gridy = row; + constraints.weightx = 0; + constraints.fill = GridBagConstraints.HORIZONTAL; + target.add(label, constraints); + + constraints.gridx = 2; + constraints.gridy = row; + constraints.weightx = 1; + constraints.fill = GridBagConstraints.HORIZONTAL; + target.add(comp, constraints); + } + + public JComboBox getAccountSelection() { + return accountSelection; + } + + public JButton getLogout() { + return logout; + } + + public JButton getTransfer() { + return transfer; + } + + public JButton getDeposit() { + return deposit; + } + + public JButton getTakeoff() { + return takeoff; + } +} diff --git a/src/me/teridax/jcash/gui/login/AccountSelectionListener.java b/src/me/teridax/jcash/gui/login/AccountSelectionListener.java new file mode 100644 index 0000000..abeac4f --- /dev/null +++ b/src/me/teridax/jcash/gui/login/AccountSelectionListener.java @@ -0,0 +1,8 @@ +package me.teridax.jcash.gui.login; + +import me.teridax.jcash.banking.Profile; + +public interface AccountSelectionListener { + + void onAccountSelected(Profile account); +} diff --git a/src/me/teridax/jcash/gui/login/LoginController.java b/src/me/teridax/jcash/gui/login/LoginController.java index 543f42e..8d3ed26 100644 --- a/src/me/teridax/jcash/gui/login/LoginController.java +++ b/src/me/teridax/jcash/gui/login/LoginController.java @@ -3,6 +3,7 @@ package me.teridax.jcash.gui.login; import me.teridax.jcash.banking.Account; import me.teridax.jcash.banking.BankingManagementSystem; +import javax.swing.*; import java.awt.event.ActionEvent; import java.util.Optional; @@ -11,12 +12,11 @@ public class LoginController { private LoginView view; private LoginData data; - private Optional account; + private AccountSelectionListener listener; public LoginController(BankingManagementSystem bms) { this.view = new LoginView(); this.data = new LoginData(bms); - this.account = Optional.empty(); addActionListeners(); } @@ -46,13 +46,28 @@ public class LoginController { var blz = this.view.getBlz().getText(); var iban = this.getIban(); if (iban.isEmpty()) { + JOptionPane.showMessageDialog(null, "invalid IBAN", "Faulty login attempt", JOptionPane.ERROR_MESSAGE); return; } var pin = this.getPin(); if (pin.isEmpty()) { + JOptionPane.showMessageDialog(null, "invalid pin", "Faulty login attempt", JOptionPane.ERROR_MESSAGE); return; } - this.account = this.data.authenticateAccount(blz, iban.get(), pin.get()); + var account = this.data.authenticateAccount(blz, iban.get(), pin.get()); + if (account.isPresent()) { + this.listener.onAccountSelected(account.get()); + } else { + JOptionPane.showMessageDialog(null, "invalid login credentials", "Faulty login attempt", JOptionPane.ERROR_MESSAGE); + } + } + + public void addAccountSelectionListener(AccountSelectionListener listener) { + this.listener = listener; + } + + public LoginView getView() { + return view; } } diff --git a/src/me/teridax/jcash/gui/login/LoginData.java b/src/me/teridax/jcash/gui/login/LoginData.java index 730128e..e599931 100644 --- a/src/me/teridax/jcash/gui/login/LoginData.java +++ b/src/me/teridax/jcash/gui/login/LoginData.java @@ -2,6 +2,7 @@ package me.teridax.jcash.gui.login; import me.teridax.jcash.banking.Account; import me.teridax.jcash.banking.BankingManagementSystem; +import me.teridax.jcash.banking.Profile; import java.util.Optional; @@ -13,12 +14,12 @@ public class LoginData { this.bms = bms; } - public Optional authenticateAccount(String blz, int iban, int pin) { + public Optional authenticateAccount(String blz, int iban, int pin) { var optionalBank = bms.getBank(blz); if (optionalBank.isEmpty()) return Optional.empty(); - var account = optionalBank.get().getAccount(iban); - return account.filter(value -> value.getPin() == pin); + var profile = optionalBank.get().getAccount(iban); + return profile.filter(value -> value.getPrimaryAccount().getPin() == pin); } } diff --git a/src/me/teridax/jcash/gui/login/LoginView.java b/src/me/teridax/jcash/gui/login/LoginView.java index 7bf3043..5b1114f 100644 --- a/src/me/teridax/jcash/gui/login/LoginView.java +++ b/src/me/teridax/jcash/gui/login/LoginView.java @@ -11,9 +11,9 @@ public class LoginView extends JPanel { private final JButton login; public LoginView() { - this.blz = new JTextField(); - this.iban = new JTextField(); - this.pin = new JPasswordField(); + this.blz = new JTextField("MA2424"); + this.iban = new JTextField("4711"); + this.pin = new JPasswordField("1234"); this.login = new JButton("Login"); setLayout(new BorderLayout(16, 16)); @@ -27,7 +27,6 @@ public class LoginView extends JPanel { content.setLayout(layout); constraints.gridwidth = 4; - constraints.insets = new Insets(12,12,12,12); addInputRow(constraints, content, blz, 1, "BLZ"); @@ -72,4 +71,5 @@ public class LoginView extends JPanel { public JButton getLogin() { return login; } + }