added deposit/transfer/takeoff screen

This commit is contained in:
Sven Vogel 2023-06-22 20:36:51 +02:00
parent c34895f92e
commit affe69cf2c
14 changed files with 534 additions and 20 deletions

View File

@ -9,7 +9,6 @@ import javax.swing.*;
public class Main { public class Main {
private static Main instance; private static Main instance;
private final JFrame window; private final JFrame window;
private Main() { private Main() {

View File

@ -9,7 +9,7 @@ public abstract class Account {
private final int iban; private final int iban;
private final int pin; private final int pin;
private final double balance; private double balance;
public Account(int iban, int pin, double balance) { public Account(int iban, int pin, double balance) {
this.iban = iban; this.iban = iban;
@ -68,4 +68,17 @@ public abstract class Account {
public String getDescription() { public String getDescription() {
return String.format("%s (%s)", iban, getClass().getSimpleName()); return String.format("%s (%s)", iban, getClass().getSimpleName());
} }
public void deposit(double amount) {
this.balance += amount;
}
@Override
public String toString() {
return String.format("@Account [iban=%d, pin=%d, balance=%.2f]", iban, pin, balance);
}
public void takeoff(double amount) {
this.balance = Math.max(0, this.balance - amount);
}
} }

View File

@ -1,6 +1,7 @@
package me.teridax.jcash.banking; package me.teridax.jcash.banking;
import java.util.*; import java.util.*;
import java.util.regex.Pattern;
@SuppressWarnings("unused") @SuppressWarnings("unused")
public final class Bank { public final class Bank {
@ -46,21 +47,20 @@ public final class Bank {
} }
public static String validateBlz(String maybeBlz) { public static String validateBlz(String maybeBlz) {
var builder = new StringBuilder(); var pattern = Pattern.compile("[\\w\\d-_]+");
maybeBlz.trim().chars().filter(ch -> Character.isDigit(ch) || Character.isLetter(ch)).forEach(builder::append); var matcher = pattern.matcher(maybeBlz);
var blz = builder.toString();
if (blz.isEmpty()) { if (matcher.find())
throw new IllegalArgumentException("Bank Blz must only contain letters and digits"); return matcher.group();
}
return blz; throw new IllegalArgumentException("not a valid BLZ: " + maybeBlz);
} }
public Optional<Profile> getAccount(int iban) { public Optional<Profile> getAccount(int iban) {
for (var owner : this.accounts.entrySet()) { for (var owner : this.accounts.entrySet()) {
for (var account : owner.getValue()) { for (var account : owner.getValue()) {
if (account.getIban() == iban) { var tmp = account.getIban();
if (tmp == iban) {
return Optional.of(new Profile(owner.getKey(), this, account, getAccountsOfOwner(owner.getKey()))); return Optional.of(new Profile(owner.getKey(), this, account, getAccountsOfOwner(owner.getKey())));
} }
} }

View File

@ -56,6 +56,6 @@ public final class BankingManagementSystem {
} }
public Optional<Bank> getBank(String blz) { public Optional<Bank> 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();
} }
} }

View File

@ -2,6 +2,9 @@ package me.teridax.jcash.gui.account;
import me.teridax.jcash.Main; import me.teridax.jcash.Main;
import me.teridax.jcash.banking.Profile; import me.teridax.jcash.banking.Profile;
import me.teridax.jcash.gui.deposit.DepositDialog;
import me.teridax.jcash.gui.takeoff.TakeoffDialog;
import me.teridax.jcash.gui.transfer.TransferDialog;
public class AccountController { public class AccountController {
@ -25,6 +28,18 @@ public class AccountController {
Main.getInstance().logout(); Main.getInstance().logout();
Main.getInstance().popLoginScreen(); Main.getInstance().popLoginScreen();
}); });
this.view.getDeposit().addActionListener(e -> {
new DepositDialog(profile.getPrimaryAccount(), () -> this.view.setProfile(profile));
});
this.view.getTakeoff().addActionListener(e -> {
new TakeoffDialog(profile.getPrimaryAccount(), () -> this.view.setProfile(profile));
});
this.view.getTransfer().addActionListener(e -> {
new TransferDialog(profile.getPrimaryAccount(), () -> this.view.setProfile(profile));
});
} }
public AccountView getView() { public AccountView getView() {

View File

@ -0,0 +1,17 @@
package me.teridax.jcash.gui.deposit;
import me.teridax.jcash.banking.Account;
public class DepositDialog {
public DepositDialog(Account account, Runnable onDeposit) {
var view = new DepositView(account);
view.getDeposit().addActionListener(e -> {
account.deposit(view.getAmount());
onDeposit.run();
view.dispose();
});
view.getCancel().addActionListener(e -> view.dispose());
view.showDialog();
}
}

View File

@ -0,0 +1,124 @@
package me.teridax.jcash.gui.deposit;
import me.teridax.jcash.banking.Account;
import javax.swing.*;
import javax.swing.text.NumberFormatter;
import java.awt.*;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Locale;
public class DepositView {
private JDialog dialog;
private JButton cancel;
private JButton deposit;
private JFormattedTextField value;
public DepositView(Account account) {
createComponents(account);
layoutComponents();
}
public void showDialog() {
dialog.setModalityType(Dialog.ModalityType.APPLICATION_MODAL);
dialog.setTitle("Deposit money");
dialog.pack();
dialog.setResizable(false);
dialog.setLocationRelativeTo(null);
dialog.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
dialog.setVisible(true);
}
private NumberFormatter getNumberFormat() {
var format = NumberFormat.getNumberInstance(Locale.GERMANY);
format.setParseIntegerOnly(false);
format.setMaximumFractionDigits(2);
var formatter = new NumberFormatter(format);
formatter.setValueClass(Double.class);
formatter.setAllowsInvalid(false);
return formatter;
}
private void layoutComponents() {
dialog.getContentPane().setLayout(new GridBagLayout());
var c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 0;
c.weightx = 1;
c.weighty = 1;
c.fill = GridBagConstraints.BOTH;
c.anchor = GridBagConstraints.CENTER;
c.insets = new Insets(10, 10, 10, 10);
dialog.getContentPane().add(new JLabel("Deposit money"), c);
c.gridx = 0;
c.gridy = 1;
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.LAST_LINE_END;
c.insets = new Insets(10, 10, 10, 10);
c.weightx = 0;
dialog.getContentPane().add(new JLabel("Betrag", SwingConstants.RIGHT), c);
c.gridx = 1;
c.gridy = 1;
c.fill = GridBagConstraints.HORIZONTAL;
c.anchor = GridBagConstraints.LAST_LINE_END;
c.insets = new Insets(10, 10, 10, 10);
c.weightx = 1;
dialog.getContentPane().add(value, c);
c.gridx = 1;
c.gridy = 2;
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.LAST_LINE_END;
c.insets = new Insets(10, 10, 10, 10);
c.weightx = 0;
dialog.getContentPane().add(cancel, c);
c.gridx = 2;
c.gridy = 2;
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.LAST_LINE_END;
c.insets = new Insets(10, 10, 10, 10);
c.weightx = 0;
dialog.getContentPane().add(deposit, c);
}
private void createComponents(Account account) {
this.dialog = new JDialog();
this.cancel = new JButton("Abbrechen");
this.deposit = new JButton("Einzahlen");
this.value = new JFormattedTextField(getNumberFormat());
this.dialog.setContentPane(new JPanel(new GridBagLayout()));
}
public double getAmount() {
if (value.getText().isBlank())
return 0;
try {
return NumberFormat.getNumberInstance().parse(value.getText()).doubleValue();
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
public JButton getCancel() {
return cancel;
}
public JButton getDeposit() {
return deposit;
}
public void dispose() {
this.dialog.dispose();
}
}

View File

@ -1,6 +1,5 @@
package me.teridax.jcash.gui.login; package me.teridax.jcash.gui.login;
import me.teridax.jcash.banking.Account;
import me.teridax.jcash.banking.BankingManagementSystem; import me.teridax.jcash.banking.BankingManagementSystem;
import javax.swing.*; import javax.swing.*;
@ -9,8 +8,8 @@ import java.util.Optional;
public class LoginController { public class LoginController {
private LoginView view; private final LoginView view;
private LoginData data; private final LoginData data;
private AccountSelectionListener listener; private AccountSelectionListener listener;
@ -33,6 +32,7 @@ public class LoginController {
return Optional.empty(); return Optional.empty();
} }
} }
private Optional<Integer> getPin() { private Optional<Integer> getPin() {
try { try {
var iban = this.view.getPin().getPassword(); var iban = this.view.getPin().getPassword();

View File

@ -1,6 +1,5 @@
package me.teridax.jcash.gui.login; package me.teridax.jcash.gui.login;
import me.teridax.jcash.banking.Account;
import me.teridax.jcash.banking.BankingManagementSystem; import me.teridax.jcash.banking.BankingManagementSystem;
import me.teridax.jcash.banking.Profile; import me.teridax.jcash.banking.Profile;

View File

@ -1,18 +1,21 @@
package me.teridax.jcash.gui.login; package me.teridax.jcash.gui.login;
import javax.swing.*; import javax.swing.*;
import javax.swing.text.NumberFormatter;
import java.awt.*; import java.awt.*;
import java.text.NumberFormat;
public class LoginView extends JPanel { public class LoginView extends JPanel {
private final JTextField blz; private final JFormattedTextField blz;
private final JTextField iban; private final JFormattedTextField iban;
private final JPasswordField pin; private final JPasswordField pin;
private final JButton login; private final JButton login;
public LoginView() { public LoginView() {
this.blz = new JTextField("MA2424"); this.blz = new JFormattedTextField("MA2424");
this.iban = new JTextField("4711"); this.iban = new JFormattedTextField(getNumberFormat());
this.iban.setText("4711");
this.pin = new JPasswordField("1234"); this.pin = new JPasswordField("1234");
this.login = new JButton("Login"); this.login = new JButton("Login");
@ -41,6 +44,19 @@ public class LoginView extends JPanel {
content.add(login, constraints); content.add(login, constraints);
} }
private NumberFormatter getNumberFormat() {
var format = NumberFormat.getIntegerInstance();
format.setGroupingUsed(false);
var formatter = new NumberFormatter(format);
formatter.setValueClass(Integer.class);
formatter.setMinimum(0);
formatter.setMaximum(Integer.MAX_VALUE);
formatter.setAllowsInvalid(false);
return formatter;
}
private void addInputRow(GridBagConstraints constraints, JComponent target, JComponent comp, int row, String name) { private void addInputRow(GridBagConstraints constraints, JComponent target, JComponent comp, int row, String name) {
constraints.gridwidth = 1; constraints.gridwidth = 1;
constraints.gridx = 1; constraints.gridx = 1;
@ -71,5 +87,4 @@ public class LoginView extends JPanel {
public JButton getLogin() { public JButton getLogin() {
return login; return login;
} }
} }

View File

@ -0,0 +1,17 @@
package me.teridax.jcash.gui.takeoff;
import me.teridax.jcash.banking.Account;
public class TakeoffDialog {
public TakeoffDialog(Account account, Runnable onDeposit) {
var view = new TakeoffView(account);
view.getDeposit().addActionListener(e -> {
account.takeoff(view.getAmount());
onDeposit.run();
view.dispose();
});
view.getCancel().addActionListener(e -> view.dispose());
view.showDialog();
}
}

View File

@ -0,0 +1,130 @@
package me.teridax.jcash.gui.takeoff;
import me.teridax.jcash.banking.Account;
import javax.swing.*;
import javax.swing.text.NumberFormatter;
import java.awt.*;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Locale;
import static javax.swing.JOptionPane.ERROR_MESSAGE;
import static javax.swing.JOptionPane.showMessageDialog;
public class TakeoffView {
private JDialog dialog;
private JButton cancel;
private JButton deposit;
private JFormattedTextField value;
public TakeoffView(Account account) {
createComponents(account);
layoutComponents();
}
public void showDialog() {
dialog.setModalityType(Dialog.ModalityType.APPLICATION_MODAL);
dialog.setTitle("Deposit money");
dialog.pack();
dialog.setResizable(false);
dialog.setLocationRelativeTo(null);
dialog.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
dialog.setVisible(true);
}
private NumberFormatter getNumberFormat(double balance) {
var format = NumberFormat.getNumberInstance(Locale.GERMANY);
format.setParseIntegerOnly(false);
format.setMaximumFractionDigits(2);
var formatter = new NumberFormatter(format);
formatter.setValueClass(Double.class);
formatter.setAllowsInvalid(true);
formatter.setMaximum(balance);
return formatter;
}
private void layoutComponents() {
dialog.getContentPane().setLayout(new GridBagLayout());
var c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 0;
c.weightx = 1;
c.weighty = 1;
c.fill = GridBagConstraints.BOTH;
c.anchor = GridBagConstraints.CENTER;
c.insets = new Insets(10, 10, 10, 10);
dialog.getContentPane().add(new JLabel("Takeoff money"), c);
c.gridx = 0;
c.gridy = 1;
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.LAST_LINE_END;
c.insets = new Insets(10, 10, 10, 10);
c.weightx = 0;
dialog.getContentPane().add(new JLabel("Betrag", SwingConstants.RIGHT), c);
c.gridx = 1;
c.gridy = 1;
c.fill = GridBagConstraints.HORIZONTAL;
c.anchor = GridBagConstraints.LAST_LINE_END;
c.insets = new Insets(10, 10, 10, 10);
c.weightx = 1;
dialog.getContentPane().add(value, c);
c.gridx = 1;
c.gridy = 2;
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.LAST_LINE_END;
c.insets = new Insets(10, 10, 10, 10);
c.weightx = 0;
dialog.getContentPane().add(cancel, c);
c.gridx = 2;
c.gridy = 2;
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.LAST_LINE_END;
c.insets = new Insets(10, 10, 10, 10);
c.weightx = 0;
dialog.getContentPane().add(deposit, c);
}
private void createComponents(Account account) {
this.dialog = new JDialog();
this.cancel = new JButton("Abbrechen");
this.deposit = new JButton("Auszahlen");
this.value = new JFormattedTextField(getNumberFormat(account.getBalance()));
this.dialog.setContentPane(new JPanel(new GridBagLayout()));
}
public double getAmount() {
if (value.getText().isBlank()) {
showMessageDialog(null, "invalid amount", "currency must not be blank", ERROR_MESSAGE);
return 0;
}
try {
return NumberFormat.getNumberInstance().parse(value.getText()).doubleValue();
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
public JButton getCancel() {
return cancel;
}
public JButton getDeposit() {
return deposit;
}
public void dispose() {
this.dialog.dispose();
}
}

View File

@ -0,0 +1,17 @@
package me.teridax.jcash.gui.transfer;
import me.teridax.jcash.banking.Account;
public class TransferDialog {
public TransferDialog(Account account, Runnable onDeposit) {
var view = new TransferView(account);
view.getDeposit().addActionListener(e -> {
account.takeoff(view.getAmount());
onDeposit.run();
view.dispose();
});
view.getCancel().addActionListener(e -> view.dispose());
view.showDialog();
}
}

View File

@ -0,0 +1,168 @@
package me.teridax.jcash.gui.transfer;
import me.teridax.jcash.banking.Account;
import javax.swing.*;
import javax.swing.text.NumberFormatter;
import java.awt.*;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Locale;
import static javax.swing.JOptionPane.ERROR_MESSAGE;
import static javax.swing.JOptionPane.showMessageDialog;
public class TransferView {
private JDialog dialog;
private JButton cancel;
private JButton deposit;
private JFormattedTextField iban;
private JFormattedTextField blz;
private JFormattedTextField value;
public TransferView(Account account) {
createComponents(account);
layoutComponents();
}
public void showDialog() {
dialog.setModalityType(Dialog.ModalityType.APPLICATION_MODAL);
dialog.setTitle("Deposit money");
dialog.pack();
dialog.setResizable(false);
dialog.setLocationRelativeTo(null);
dialog.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
dialog.setVisible(true);
}
private NumberFormatter getNumberFormat(double balance) {
var format = NumberFormat.getNumberInstance(Locale.GERMANY);
format.setParseIntegerOnly(false);
format.setMaximumFractionDigits(2);
var formatter = new NumberFormatter(format);
formatter.setValueClass(Double.class);
formatter.setAllowsInvalid(true);
formatter.setMaximum(balance);
return formatter;
}
private void layoutComponents() {
dialog.getContentPane().setLayout(new GridBagLayout());
var c = new GridBagConstraints();
c.gridx = 0;
c.gridy = 0;
c.weightx = 1;
c.weighty = 1;
c.fill = GridBagConstraints.BOTH;
c.anchor = GridBagConstraints.CENTER;
c.insets = new Insets(10, 10, 10, 10);
dialog.getContentPane().add(new JLabel("Takeoff money"), c);
c.gridx = 0;
c.gridy = 1;
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.LAST_LINE_END;
c.insets = new Insets(10, 10, 10, 10);
c.weightx = 0;
dialog.getContentPane().add(new JLabel("BLZ", SwingConstants.RIGHT), c);
c.gridx = 1;
c.gridy = 1;
c.fill = GridBagConstraints.HORIZONTAL;
c.anchor = GridBagConstraints.LAST_LINE_END;
c.insets = new Insets(10, 10, 10, 10);
c.weightx = 1;
dialog.getContentPane().add(blz, c);
c.gridx = 2;
c.gridy = 1;
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.LAST_LINE_END;
c.insets = new Insets(10, 10, 10, 10);
c.weightx = 0;
dialog.getContentPane().add(new JLabel("IBAN", SwingConstants.RIGHT), c);
c.gridx = 3;
c.gridy = 1;
c.fill = GridBagConstraints.HORIZONTAL;
c.anchor = GridBagConstraints.LAST_LINE_END;
c.insets = new Insets(10, 10, 10, 10);
c.weightx = 1;
dialog.getContentPane().add(iban, c);
c.gridx = 0;
c.gridy = 2;
c.fill = GridBagConstraints.NONE;
c.anchor = GridBagConstraints.LAST_LINE_END;
c.insets = new Insets(10, 10, 10, 10);
c.weightx = 0;
dialog.getContentPane().add(new JLabel("Betrag", SwingConstants.RIGHT), c);
c.gridx = 1;
c.gridy = 2;
c.fill = GridBagConstraints.HORIZONTAL;
c.anchor = GridBagConstraints.LAST_LINE_END;
c.insets = new Insets(10, 10, 10, 10);
c.weightx = 1;
dialog.getContentPane().add(value, c);
c.gridx = 2;
c.gridy = 3;
c.fill = GridBagConstraints.HORIZONTAL;
c.anchor = GridBagConstraints.LAST_LINE_END;
c.insets = new Insets(10, 10, 10, 10);
c.weightx = 1;
dialog.getContentPane().add(cancel, c);
c.gridx = 3;
c.gridy = 3;
c.fill = GridBagConstraints.HORIZONTAL;
c.anchor = GridBagConstraints.LAST_LINE_END;
c.insets = new Insets(10, 10, 10, 10);
c.weightx = 1;
dialog.getContentPane().add(deposit, c);
dialog.getContentPane().add(value, c);
}
private void createComponents(Account account) {
this.dialog = new JDialog();
this.cancel = new JButton("Abbrechen");
this.deposit = new JButton("Auszahlen");
this.value = new JFormattedTextField(getNumberFormat(account.getBalance()));
this.iban = new JFormattedTextField();
this.blz = new JFormattedTextField();
this.dialog.setContentPane(new JPanel(new GridBagLayout()));
}
public double getAmount() {
if (value.getText().isBlank()) {
showMessageDialog(null, "invalid amount", "currency must not be blank", ERROR_MESSAGE);
return 0;
}
try {
return NumberFormat.getNumberInstance().parse(value.getText()).doubleValue();
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
public JButton getCancel() {
return cancel;
}
public JButton getDeposit() {
return deposit;
}
public void dispose() {
this.dialog.dispose();
}
}