added javadoc and implemented transfer functionality
This commit is contained in:
parent
a9ae1dc55a
commit
d5d5a50e2d
|
@ -65,7 +65,7 @@ public final class Main {
|
||||||
|
|
||||||
// when we have logged in set the account viewer as window content
|
// when we have logged in set the account viewer as window content
|
||||||
login.addAccountSelectionListener(account -> {
|
login.addAccountSelectionListener(account -> {
|
||||||
var profileCont = new AccountController(account);
|
var profileCont = new AccountController(account, login.getData().getBms());
|
||||||
this.window.setContentPane(profileCont.getView());
|
this.window.setContentPane(profileCont.getView());
|
||||||
this.window.revalidate();
|
this.window.revalidate();
|
||||||
this.window.repaint();
|
this.window.repaint();
|
||||||
|
@ -78,6 +78,7 @@ public final class Main {
|
||||||
|
|
||||||
} catch (IllegalStateException e) {
|
} catch (IllegalStateException e) {
|
||||||
System.out.println("no file selected. goodbye");
|
System.out.println("no file selected. goodbye");
|
||||||
|
System.exit(0);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,27 @@
|
||||||
package me.teridax.jcash.banking;
|
package me.teridax.jcash.banking;
|
||||||
|
|
||||||
import me.teridax.jcash.decode.StringUtils;
|
import me.teridax.jcash.decode.StringDecoder;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Base class for bank accounts.
|
||||||
|
* Stores the iban, pin and balance.
|
||||||
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public abstract class Account {
|
public abstract class Account {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* International bank account number
|
||||||
|
*/
|
||||||
private final int iban;
|
private final int iban;
|
||||||
|
/**
|
||||||
|
* Personal identification number
|
||||||
|
*/
|
||||||
private final int pin;
|
private final int pin;
|
||||||
|
/**
|
||||||
|
* Balance of this account
|
||||||
|
*/
|
||||||
private double balance;
|
private double balance;
|
||||||
|
|
||||||
public Account(int iban, int pin, double balance) {
|
public Account(int iban, int pin, double balance) {
|
||||||
|
@ -17,20 +30,30 @@ public abstract class Account {
|
||||||
this.balance = balance;
|
this.balance = balance;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Account fromColumns(String[] columns) {
|
/**
|
||||||
|
* Parses a row of a fixed amount of columns into an account.
|
||||||
|
* This function will attempt to create an instance of two classes which inherit from Account.
|
||||||
|
* @param columns array of 6 strings
|
||||||
|
* @return either an instance of {@link me.teridax.jcash.banking.SavingsAccount} or an instance of {@link me.teridax.jcash.banking.CurrentAccount}
|
||||||
|
* @throws IllegalArgumentException if the account type cannot be determined or the provided data is invalid
|
||||||
|
* @throws NullPointerException if columns is null
|
||||||
|
*/
|
||||||
|
public static Account fromColumns(String[] columns) throws IllegalArgumentException, NullPointerException {
|
||||||
Objects.requireNonNull(columns);
|
Objects.requireNonNull(columns);
|
||||||
|
|
||||||
var iban = StringUtils.decodeUniqueIdentificationNumber(columns[0]);
|
// deserialize fields
|
||||||
var pin = StringUtils.decodeUniqueIdentificationNumber(columns[1]);
|
var iban = StringDecoder.decodeUniqueIdentificationNumber(columns[0]);
|
||||||
var balance = StringUtils.decodeCurrency(columns[2]);
|
var pin = StringDecoder.decodeUniqueIdentificationNumber(columns[1]);
|
||||||
var type = StringUtils.decodeName(columns[3]);
|
var balance = StringDecoder.decodeCurrency(columns[2]);
|
||||||
|
var type = StringDecoder.decodeName(columns[3]);
|
||||||
|
|
||||||
|
// try to detect the specific runtime class to deserialize
|
||||||
try {
|
try {
|
||||||
if (type.equals("Sparkonto")) {
|
if (type.equals("Sparkonto")) {
|
||||||
var interest = StringUtils.decodePercent(columns[4]);
|
var interest = StringDecoder.decodePercent(columns[4]);
|
||||||
return new SavingsAccount(iban, pin, balance, interest);
|
return new SavingsAccount(iban, pin, balance, interest);
|
||||||
} else if (type.equals("Girokonto")) {
|
} else if (type.equals("Girokonto")) {
|
||||||
var overdraft = StringUtils.decodeCurrency(columns[5]);
|
var overdraft = StringDecoder.decodeCurrency(columns[5]);
|
||||||
return new CurrentAccount(iban, pin, balance, overdraft);
|
return new CurrentAccount(iban, pin, balance, overdraft);
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalArgumentException("Invalid account type: " + type);
|
throw new IllegalArgumentException("Invalid account type: " + type);
|
||||||
|
@ -65,6 +88,12 @@ public abstract class Account {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a description of the account in form a string.
|
||||||
|
* This method is not equal to {@link #toString()} but is intended to be
|
||||||
|
* a method used to retrieve a formatted representation for guis.
|
||||||
|
* @return a basic description of the account in form a string
|
||||||
|
*/
|
||||||
public String getDescription() {
|
public String getDescription() {
|
||||||
return String.format("%s (%s)", iban, getClass().getSimpleName());
|
return String.format("%s (%s)", iban, getClass().getSimpleName());
|
||||||
}
|
}
|
||||||
|
@ -78,6 +107,11 @@ public abstract class Account {
|
||||||
return String.format("@Account [iban=%d, pin=%d, balance=%.2f]", iban, pin, balance);
|
return String.format("@Account [iban=%d, pin=%d, balance=%.2f]", iban, pin, balance);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Takeoff a certain amount of money from this accounts balance.
|
||||||
|
* Saturates the result if the value to subtract is greater than the balance present.
|
||||||
|
* @param amount the amount of money to subtract from the accounts balance
|
||||||
|
*/
|
||||||
public void takeoff(double amount) {
|
public void takeoff(double amount) {
|
||||||
this.balance = Math.max(0, this.balance - amount);
|
this.balance = Math.max(0, this.balance - amount);
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,10 +3,24 @@ package me.teridax.jcash.banking;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bank storing a name, blz and a list of owners and their accounts for this bank.
|
||||||
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public final class Bank {
|
public final class Bank {
|
||||||
|
/**
|
||||||
|
* The name of the bank
|
||||||
|
*/
|
||||||
private final String name;
|
private final String name;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bankleitzahl. Identification number of banks in germany
|
||||||
|
*/
|
||||||
private final String blz;
|
private final String blz;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A map of banking accounts associated with their respective owner
|
||||||
|
*/
|
||||||
private final Map<Owner, Set<Account>> accounts;
|
private final Map<Owner, Set<Account>> accounts;
|
||||||
|
|
||||||
Bank(String blz, String name) {
|
Bank(String blz, String name) {
|
||||||
|
@ -23,6 +37,13 @@ public final class Bank {
|
||||||
return name;
|
return name;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new account and its associated owner to this bank.
|
||||||
|
* If the owner is already present the account is added to the existing owner.
|
||||||
|
* If the account is already present for the owner the old account gets overwritten.
|
||||||
|
* @param owner the owner of the account
|
||||||
|
* @param account the account of the owner
|
||||||
|
*/
|
||||||
public void addAccount(Owner owner, Account account) {
|
public void addAccount(Owner owner, Account account) {
|
||||||
var set = this.accounts.getOrDefault(owner, new HashSet<>());
|
var set = this.accounts.getOrDefault(owner, new HashSet<>());
|
||||||
set.add(account);
|
set.add(account);
|
||||||
|
@ -42,12 +63,23 @@ public final class Bank {
|
||||||
return Objects.hash(blz);
|
return Objects.hash(blz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve all accounts owned by the specific owner.
|
||||||
|
* @param owner the owner for which accounts are to be retrieved
|
||||||
|
* @return all accounts owned by the owner and managed by this bank
|
||||||
|
*/
|
||||||
public Account[] getAccountsOfOwner(Owner owner) {
|
public Account[] getAccountsOfOwner(Owner owner) {
|
||||||
return accounts.get(owner).toArray(Account[]::new);
|
return accounts.get(owner).toArray(Account[]::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String validateBlz(String maybeBlz) {
|
/**
|
||||||
var pattern = Pattern.compile("[\\w\\d-_]+");
|
* Validates the given BLZ. If the blz is not valid an exception is thrown.
|
||||||
|
* @param maybeBlz a string to be tested for being a blz
|
||||||
|
* @return returns the correctly formatted blz
|
||||||
|
* @throws IllegalArgumentException if the supplied argument is not a valid blz
|
||||||
|
*/
|
||||||
|
public static String validateBlz(String maybeBlz) throws IllegalArgumentException {
|
||||||
|
var pattern = Pattern.compile("[\\w-_]+");
|
||||||
var matcher = pattern.matcher(maybeBlz);
|
var matcher = pattern.matcher(maybeBlz);
|
||||||
|
|
||||||
if (matcher.find())
|
if (matcher.find())
|
||||||
|
@ -56,11 +88,17 @@ public final class Bank {
|
||||||
throw new IllegalArgumentException("not a valid BLZ: " + maybeBlz);
|
throw new IllegalArgumentException("not a valid BLZ: " + maybeBlz);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a profile of the specified international bank account number.
|
||||||
|
* @param iban the number to create a profile for
|
||||||
|
* @return the profile for the iban account
|
||||||
|
*/
|
||||||
public Optional<Profile> getAccount(int iban) {
|
public Optional<Profile> getAccount(int iban) {
|
||||||
|
// find the account which has the supplied iban
|
||||||
|
|
||||||
for (var owner : this.accounts.entrySet()) {
|
for (var owner : this.accounts.entrySet()) {
|
||||||
for (var account : owner.getValue()) {
|
for (var account : owner.getValue()) {
|
||||||
var tmp = account.getIban();
|
if (iban == 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())));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,42 +1,90 @@
|
||||||
package me.teridax.jcash.banking;
|
package me.teridax.jcash.banking;
|
||||||
|
|
||||||
import me.teridax.jcash.decode.StringUtils;
|
import me.teridax.jcash.decode.StringDecoder;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Management system for banks and all accounts provided by these banks and their respective account owners.
|
||||||
|
* This class serves a read only database which can only modify runtime data without any respect to CRUD or the ACID
|
||||||
|
* principles.
|
||||||
|
*/
|
||||||
public final class BankingManagementSystem {
|
public final class BankingManagementSystem {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A set of banks
|
||||||
|
*/
|
||||||
private final Set<Bank> banks;
|
private final Set<Bank> banks;
|
||||||
|
|
||||||
private BankingManagementSystem() {
|
private BankingManagementSystem() {
|
||||||
this.banks = new HashSet<>();
|
this.banks = new HashSet<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility method for retrieving the tail of a string array.
|
||||||
|
* This method return all items which follow the n-th index denoted by index.
|
||||||
|
* @param array the array to take the tail of
|
||||||
|
* @param index the amount trailing indices to skip
|
||||||
|
* @return an array containing the last elements of the supplied array
|
||||||
|
*/
|
||||||
private static String[] tail(String[] array, int index) {
|
private static String[] tail(String[] array, int index) {
|
||||||
return Arrays.stream(array).skip(index).toArray(String[]::new);
|
return Arrays.stream(array).skip(index).toArray(String[]::new);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static BankingManagementSystem loadFromCsv(Path file) {
|
/**
|
||||||
|
* Loads an instance of this class from a csv file.
|
||||||
|
* The csv file must comply to the formats of {@link StringDecoder} and must contain
|
||||||
|
* the following columns in this exact order:
|
||||||
|
* <ol>
|
||||||
|
* <li>Bank name</li>
|
||||||
|
* <li>Bank BLZ</li>
|
||||||
|
* <li>Account IBAN</li>
|
||||||
|
* <li>Account PIN</li>
|
||||||
|
* <li>Account Balance</li>
|
||||||
|
* <li>Account type</li>
|
||||||
|
* <li>Account Interest rate</li>
|
||||||
|
* <li>Account Overdraft</li>
|
||||||
|
* <li>Owner uuid</li>
|
||||||
|
* <li>Owner family name</li>
|
||||||
|
* <li>Owner name</li>
|
||||||
|
* <li>Owner street</li>
|
||||||
|
* <li>Owner plz</li>
|
||||||
|
* <li>Owner city</li>
|
||||||
|
* </ol>
|
||||||
|
* The file can contain a header line which gets skipped when reading.
|
||||||
|
* Note that the first line is always skipped and the name of every column is not checked in any way.
|
||||||
|
* @param file the file to parse
|
||||||
|
* @throws IllegalArgumentException if the file cannot be read or the containing data is invalid
|
||||||
|
* @return a valid BMS
|
||||||
|
*/
|
||||||
|
public static BankingManagementSystem loadFromCsv(Path file) throws IllegalArgumentException {
|
||||||
try {
|
try {
|
||||||
var bms = new BankingManagementSystem();
|
var bms = new BankingManagementSystem();
|
||||||
var content = Files.readString(file);
|
var content = Files.readString(file);
|
||||||
|
|
||||||
|
// read line by line
|
||||||
|
// and skip the first line
|
||||||
content.lines().skip(1).forEach(line -> {
|
content.lines().skip(1).forEach(line -> {
|
||||||
|
// split the line into columns
|
||||||
var columns = line.split(";");
|
var columns = line.split(";");
|
||||||
|
|
||||||
|
// one line must contain exactly 14 columns
|
||||||
if (columns.length != 14)
|
if (columns.length != 14)
|
||||||
throw new IllegalArgumentException("invalid column count: " + columns.length);
|
throw new IllegalArgumentException("invalid column count: " + columns.length);
|
||||||
|
|
||||||
|
// read basic fields
|
||||||
var owner = Owner.fromColumns(tail(columns, 8));
|
var owner = Owner.fromColumns(tail(columns, 8));
|
||||||
var account = Account.fromColumns(tail(columns, 2));
|
var account = Account.fromColumns(tail(columns, 2));
|
||||||
|
|
||||||
var blz = Bank.validateBlz(columns[1]);
|
var blz = Bank.validateBlz(columns[1]);
|
||||||
var name = StringUtils.decodeName(columns[0]);
|
var name = StringDecoder.decodeName(columns[0]);
|
||||||
var bankOfLine = new Bank(blz, name);
|
var bankOfLine = new Bank(blz, name);
|
||||||
|
|
||||||
|
// add banks to bms
|
||||||
|
|
||||||
var bankOfSet = bms.banks.stream().filter(b -> b.equals(bankOfLine)).findFirst();
|
var bankOfSet = bms.banks.stream().filter(b -> b.equals(bankOfLine)).findFirst();
|
||||||
if (bankOfSet.isPresent()) {
|
if (bankOfSet.isPresent()) {
|
||||||
bankOfSet.get().addAccount(owner, account);
|
bankOfSet.get().addAccount(owner, account);
|
||||||
|
@ -55,6 +103,11 @@ public final class BankingManagementSystem {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a bank with the given blz.
|
||||||
|
* @param blz the blz to search bank of
|
||||||
|
* @return the bank with this blz or none
|
||||||
|
*/
|
||||||
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();
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,14 @@
|
||||||
package me.teridax.jcash.banking;
|
package me.teridax.jcash.banking;
|
||||||
|
|
||||||
public class CurrentAccount extends Account {
|
/**
|
||||||
|
* Immutable currency account storing only overdraft.
|
||||||
|
* English equivalent to "Girokonto"
|
||||||
|
*/
|
||||||
|
public final class CurrentAccount extends Account {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overdraft amount in currency.
|
||||||
|
*/
|
||||||
private final double overdraft;
|
private final double overdraft;
|
||||||
|
|
||||||
public CurrentAccount(int iban, int pin, double balance, double overdraft) {
|
public CurrentAccount(int iban, int pin, double balance, double overdraft) {
|
||||||
|
|
|
@ -4,7 +4,7 @@ import org.junit.Test;
|
||||||
|
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
|
|
||||||
public class Tests {
|
public class DataClassTests {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void test() {
|
public void test() {
|
|
@ -1,17 +1,26 @@
|
||||||
package me.teridax.jcash.banking;
|
package me.teridax.jcash.banking;
|
||||||
|
|
||||||
import me.teridax.jcash.decode.StringUtils;
|
import me.teridax.jcash.decode.StringDecoder;
|
||||||
|
|
||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a person owning an account.
|
||||||
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public final class Owner {
|
public final class Owner {
|
||||||
private int uid;
|
/**
|
||||||
private String familyName;
|
* unique identifier
|
||||||
private String name;
|
*/
|
||||||
private String street;
|
private final int uid;
|
||||||
private int zip;
|
private final String familyName;
|
||||||
private String city;
|
private final String name;
|
||||||
|
private final String street;
|
||||||
|
/**
|
||||||
|
* postal code
|
||||||
|
*/
|
||||||
|
private final int zip;
|
||||||
|
private final String city;
|
||||||
|
|
||||||
private Owner(int uid, String familyName, String name, int zip, String city, String street) {
|
private Owner(int uid, String familyName, String name, int zip, String city, String street) {
|
||||||
this.uid = uid;
|
this.uid = uid;
|
||||||
|
@ -22,18 +31,26 @@ public final class Owner {
|
||||||
this.street = street;
|
this.street = street;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new instance of this class parsed from the columns.
|
||||||
|
* @param columns the fields of this class as strings
|
||||||
|
* @return an instance of this class
|
||||||
|
* @throws IllegalArgumentException if the supplied columns is invalid
|
||||||
|
* @throws NullPointerException if columns is null
|
||||||
|
*/
|
||||||
public static Owner fromColumns(String... columns) throws IllegalArgumentException, NullPointerException {
|
public static Owner fromColumns(String... columns) throws IllegalArgumentException, NullPointerException {
|
||||||
Objects.requireNonNull(columns);
|
Objects.requireNonNull(columns);
|
||||||
|
|
||||||
if (columns.length != 6)
|
if (columns.length != 6)
|
||||||
throw new IllegalArgumentException("Invalid number of columns: " + columns.length);
|
throw new IllegalArgumentException("Invalid number of columns: " + columns.length);
|
||||||
|
|
||||||
var uid = StringUtils.decodeUniqueIdentificationNumber(columns[0]);
|
// decode fields
|
||||||
var familyName = StringUtils.decodeName(columns[1]);
|
var uid = StringDecoder.decodeUniqueIdentificationNumber(columns[0]);
|
||||||
var name = StringUtils.decodeName(columns[2]);
|
var familyName = StringDecoder.decodeName(columns[1]);
|
||||||
var street = StringUtils.decodeStreet(columns[3]);
|
var name = StringDecoder.decodeName(columns[2]);
|
||||||
var zip = StringUtils.decodeUniqueIdentificationNumber(columns[4]);
|
var street = StringDecoder.decodeStreet(columns[3]);
|
||||||
var city = StringUtils.decodeName(columns[5]);
|
var zip = StringDecoder.decodeUniqueIdentificationNumber(columns[4]);
|
||||||
|
var city = StringDecoder.decodeName(columns[5]);
|
||||||
|
|
||||||
return new Owner(uid, familyName, name, zip, city, street);
|
return new Owner(uid, familyName, name, zip, city, street);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,17 @@
|
||||||
package me.teridax.jcash.banking;
|
package me.teridax.jcash.banking;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Groups an owner and all of its accounts registered at a specific bank together.
|
||||||
|
* The profile is oriented around a primary account of the owner.
|
||||||
|
* This class is meant to be a read only reference for easier runtime processing of
|
||||||
|
* data packed into nested structure of objects.
|
||||||
|
*/
|
||||||
public class Profile {
|
public class Profile {
|
||||||
|
|
||||||
private Owner owner;
|
private final Owner owner;
|
||||||
private Bank bank;
|
private final Bank bank;
|
||||||
private Account primaryAccount;
|
private Account primaryAccount;
|
||||||
private Account[] accounts;
|
private final Account[] accounts;
|
||||||
|
|
||||||
public Profile(Owner owner, Bank bank, Account account, Account[] accounts) {
|
public Profile(Owner owner, Bank bank, Account account, Account[] accounts) {
|
||||||
this.owner = owner;
|
this.owner = owner;
|
||||||
|
@ -30,6 +36,11 @@ public class Profile {
|
||||||
return accounts;
|
return accounts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set the primary account of this profile based on a descriptive text.
|
||||||
|
* This method may not change anything if no account can be found with a matching description
|
||||||
|
* @param description the description to find a matching account for
|
||||||
|
*/
|
||||||
public void setPrimaryAccount(String description) {
|
public void setPrimaryAccount(String description) {
|
||||||
for (Account account : accounts) {
|
for (Account account : accounts) {
|
||||||
if (account.getDescription().equals(description)) {
|
if (account.getDescription().equals(description)) {
|
||||||
|
|
|
@ -1,8 +1,15 @@
|
||||||
package me.teridax.jcash.banking;
|
package me.teridax.jcash.banking;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Savings account representing a german "Sparkonto".
|
||||||
|
* To the balance a certain interest rate is added.
|
||||||
|
*/
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
public class SavingsAccount extends Account {
|
public final class SavingsAccount extends Account {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* interest rate applied to the balance of the super class
|
||||||
|
*/
|
||||||
private final double interest;
|
private final double interest;
|
||||||
|
|
||||||
public SavingsAccount(int iban, int pin, double balance, double interest) {
|
public SavingsAccount(int iban, int pin, double balance, double interest) {
|
||||||
|
|
|
@ -14,7 +14,7 @@ import static junit.framework.TestCase.assertEquals;
|
||||||
* Utility class for converting various single line strings into a specific data type according
|
* Utility class for converting various single line strings into a specific data type according
|
||||||
* to a format mostly dictated by a locale.
|
* to a format mostly dictated by a locale.
|
||||||
*/
|
*/
|
||||||
public class StringUtils {
|
public class StringDecoder {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Locale to use when converting strings
|
* Locale to use when converting strings
|
|
@ -1,18 +1,26 @@
|
||||||
package me.teridax.jcash.gui.account;
|
package me.teridax.jcash.gui.account;
|
||||||
|
|
||||||
import me.teridax.jcash.Main;
|
import me.teridax.jcash.Main;
|
||||||
|
import me.teridax.jcash.banking.BankingManagementSystem;
|
||||||
import me.teridax.jcash.banking.Profile;
|
import me.teridax.jcash.banking.Profile;
|
||||||
import me.teridax.jcash.gui.deposit.DepositDialog;
|
import me.teridax.jcash.gui.deposit.DepositDialog;
|
||||||
import me.teridax.jcash.gui.takeoff.TakeoffDialog;
|
import me.teridax.jcash.gui.takeoff.TakeoffDialog;
|
||||||
import me.teridax.jcash.gui.transfer.TransferDialog;
|
import me.teridax.jcash.gui.transfer.TransferDialog;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Controller for controlling the gui of an account.
|
||||||
|
*/
|
||||||
public class AccountController {
|
public class AccountController {
|
||||||
|
private final AccountData data;
|
||||||
|
/**
|
||||||
|
* GUI if an account
|
||||||
|
*/
|
||||||
private final AccountView view;
|
private final AccountView view;
|
||||||
|
|
||||||
public AccountController(Profile profile) {
|
public AccountController(Profile profile, BankingManagementSystem bms) {
|
||||||
this.view = new AccountView();
|
this.view = new AccountView();
|
||||||
this.view.setProfile(profile);
|
this.view.setProfile(profile);
|
||||||
|
this.data = new AccountData(bms);
|
||||||
|
|
||||||
createListeners(profile);
|
createListeners(profile);
|
||||||
}
|
}
|
||||||
|
@ -29,17 +37,11 @@ public class AccountController {
|
||||||
Main.getInstance().showLoginScreen();
|
Main.getInstance().showLoginScreen();
|
||||||
});
|
});
|
||||||
|
|
||||||
this.view.getDeposit().addActionListener(e -> {
|
this.view.getDeposit().addActionListener(e -> new DepositDialog(profile.getPrimaryAccount(), () -> this.view.setProfile(profile)));
|
||||||
new DepositDialog(profile.getPrimaryAccount(), () -> this.view.setProfile(profile));
|
|
||||||
});
|
|
||||||
|
|
||||||
this.view.getTakeoff().addActionListener(e -> {
|
this.view.getTakeoff().addActionListener(e -> new TakeoffDialog(profile.getPrimaryAccount(), () -> this.view.setProfile(profile)));
|
||||||
new TakeoffDialog(profile.getPrimaryAccount(), () -> this.view.setProfile(profile));
|
|
||||||
});
|
|
||||||
|
|
||||||
this.view.getTransfer().addActionListener(e -> {
|
this.view.getTransfer().addActionListener(e -> new TransferDialog(profile.getPrimaryAccount(), data.getBms(), () -> this.view.setProfile(profile)));
|
||||||
new TransferDialog(profile.getPrimaryAccount(), () -> this.view.setProfile(profile));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public AccountView getView() {
|
public AccountView getView() {
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
package me.teridax.jcash.gui.account;
|
||||||
|
|
||||||
|
import me.teridax.jcash.banking.BankingManagementSystem;
|
||||||
|
|
||||||
|
public class AccountData {
|
||||||
|
|
||||||
|
private final BankingManagementSystem bms;
|
||||||
|
|
||||||
|
public AccountData(BankingManagementSystem bms) {
|
||||||
|
this.bms = bms;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BankingManagementSystem getBms() {
|
||||||
|
return bms;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,11 +1,13 @@
|
||||||
package me.teridax.jcash.gui.account;
|
package me.teridax.jcash.gui.account;
|
||||||
|
|
||||||
import me.teridax.jcash.banking.*;
|
import me.teridax.jcash.banking.*;
|
||||||
import me.teridax.jcash.decode.StringUtils;
|
import me.teridax.jcash.decode.StringDecoder;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
|
|
||||||
|
import static javax.swing.SwingConstants.RIGHT;
|
||||||
|
|
||||||
public class AccountView extends JPanel {
|
public class AccountView extends JPanel {
|
||||||
|
|
||||||
private JTextField iban;
|
private JTextField iban;
|
||||||
|
@ -16,13 +18,8 @@ public class AccountView extends JPanel {
|
||||||
private JTextField type;
|
private JTextField type;
|
||||||
private JTextField typeSpecialProperty;
|
private JTextField typeSpecialProperty;
|
||||||
private JTextField balance;
|
private JTextField balance;
|
||||||
|
|
||||||
private JLabel typeSpecialLabel;
|
private JLabel typeSpecialLabel;
|
||||||
|
|
||||||
private JComboBox<String> accountSelection;
|
private JComboBox<String> accountSelection;
|
||||||
|
|
||||||
private JPanel content;
|
|
||||||
|
|
||||||
private JButton logout;
|
private JButton logout;
|
||||||
private JButton transfer;
|
private JButton transfer;
|
||||||
private JButton deposit;
|
private JButton deposit;
|
||||||
|
@ -47,12 +44,12 @@ public class AccountView extends JPanel {
|
||||||
this.name.setText(owner.getName() + " " + owner.getFamilyName());
|
this.name.setText(owner.getName() + " " + owner.getFamilyName());
|
||||||
this.address.setText(owner.getStreet() + " " + owner.getCity());
|
this.address.setText(owner.getStreet() + " " + owner.getCity());
|
||||||
|
|
||||||
this.balance.setText(StringUtils.LOCAL_NUMBER_FORMAT.format(account.getBalance()) + " €");
|
this.balance.setText(StringDecoder.LOCAL_NUMBER_FORMAT.format(account.getBalance()) + " €");
|
||||||
|
|
||||||
this.type.setText(account.getClass().getSimpleName());
|
this.type.setText(account.getClass().getSimpleName());
|
||||||
if (account instanceof CurrentAccount) {
|
if (account instanceof CurrentAccount) {
|
||||||
this.typeSpecialLabel.setText("Overdraft");
|
this.typeSpecialLabel.setText("Overdraft");
|
||||||
this.typeSpecialProperty.setText( StringUtils.LOCAL_NUMBER_FORMAT.format(((CurrentAccount) account).getOverdraft()) + " €");
|
this.typeSpecialProperty.setText( StringDecoder.LOCAL_NUMBER_FORMAT.format(((CurrentAccount) account).getOverdraft()) + " €");
|
||||||
} else if (account instanceof SavingsAccount) {
|
} else if (account instanceof SavingsAccount) {
|
||||||
this.typeSpecialLabel.setText("Interest rate");
|
this.typeSpecialLabel.setText("Interest rate");
|
||||||
this.typeSpecialProperty.setText( ((SavingsAccount) account).getInterest() + " %" );
|
this.typeSpecialProperty.setText( ((SavingsAccount) account).getInterest() + " %" );
|
||||||
|
@ -67,10 +64,11 @@ public class AccountView extends JPanel {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createLayout() {
|
private void createLayout() {
|
||||||
setLayout(new BorderLayout(16, 16));
|
var content = new JPanel(new GridBagLayout());
|
||||||
add(new JScrollPane(content), BorderLayout.CENTER);
|
|
||||||
|
this.setLayout(new BorderLayout(16, 16));
|
||||||
|
this.add(new JScrollPane(content), BorderLayout.CENTER);
|
||||||
|
|
||||||
content.setLayout(new GridBagLayout());
|
|
||||||
var constraints = new GridBagConstraints();
|
var constraints = new GridBagConstraints();
|
||||||
|
|
||||||
constraints.gridwidth = 4;
|
constraints.gridwidth = 4;
|
||||||
|
@ -80,14 +78,14 @@ public class AccountView extends JPanel {
|
||||||
accountSelectionPanel.add(iban, BorderLayout.CENTER);
|
accountSelectionPanel.add(iban, BorderLayout.CENTER);
|
||||||
accountSelectionPanel.add(accountSelection, BorderLayout.EAST);
|
accountSelectionPanel.add(accountSelection, BorderLayout.EAST);
|
||||||
|
|
||||||
addInputRow(constraints, content, accountSelectionPanel, 1, new JLabel("IBAN", SwingConstants.RIGHT));
|
addInputRow(constraints, content, accountSelectionPanel, 1, new JLabel("IBAN", RIGHT));
|
||||||
addInputRow(constraints, content, name, 2, new JLabel("Name/Family-name", SwingConstants.RIGHT));
|
addInputRow(constraints, content, name, 2, new JLabel("Name/Family-name", RIGHT));
|
||||||
addInputRow(constraints, content, address, 3, new JLabel("Address", SwingConstants.RIGHT));
|
addInputRow(constraints, content, address, 3, new JLabel("Address", RIGHT));
|
||||||
addInputRow(constraints, content, bankName, 4, new JLabel("Bank", SwingConstants.RIGHT));
|
addInputRow(constraints, content, bankName, 4, new JLabel("Bank", RIGHT));
|
||||||
addInputRow(constraints, content, blz, 5, new JLabel("BLZ", SwingConstants.RIGHT));
|
addInputRow(constraints, content, blz, 5, new JLabel("BLZ", RIGHT));
|
||||||
addInputRow(constraints, content, type, 6, new JLabel("Account", SwingConstants.RIGHT));
|
addInputRow(constraints, content, type, 6, new JLabel("Account", RIGHT));
|
||||||
addInputRow(constraints, content, typeSpecialProperty, 7, typeSpecialLabel);
|
addInputRow(constraints, content, typeSpecialProperty, 7, typeSpecialLabel);
|
||||||
addInputRow(constraints, content, balance, 8, new JLabel("Balance", SwingConstants.RIGHT));
|
addInputRow(constraints, content, balance, 8, new JLabel("Balance", RIGHT));
|
||||||
|
|
||||||
var buttonPanel = Box.createHorizontalBox();
|
var buttonPanel = Box.createHorizontalBox();
|
||||||
buttonPanel.add(Box.createHorizontalStrut(4));
|
buttonPanel.add(Box.createHorizontalStrut(4));
|
||||||
|
@ -121,18 +119,25 @@ public class AccountView extends JPanel {
|
||||||
this.balance.setEditable(false);
|
this.balance.setEditable(false);
|
||||||
this.typeSpecialProperty.setEditable(false);
|
this.typeSpecialProperty.setEditable(false);
|
||||||
|
|
||||||
this.typeSpecialLabel = new JLabel("", SwingConstants.RIGHT);
|
this.typeSpecialLabel = new JLabel("", RIGHT);
|
||||||
|
|
||||||
this.accountSelection = new JComboBox<>();
|
this.accountSelection = new JComboBox<>();
|
||||||
|
|
||||||
this.content = new JPanel();
|
|
||||||
|
|
||||||
this.logout = new JButton("Logout");
|
this.logout = new JButton("Logout");
|
||||||
this.transfer = new JButton("Transfer");
|
this.transfer = new JButton("Transfer");
|
||||||
this.deposit = new JButton("Deposit");
|
this.deposit = new JButton("Deposit");
|
||||||
this.takeoff = new JButton("Takeoff");
|
this.takeoff = new JButton("Takeoff");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a new row of components to the specified target component.
|
||||||
|
* This will add label to the right side of the next row and the specified component to the left.
|
||||||
|
* @param constraints the constraint to use. Must be non-null
|
||||||
|
* @param target the base component to add a row to
|
||||||
|
* @param comp the component to add to the left side
|
||||||
|
* @param row the row to add the components to
|
||||||
|
* @param label the label to add to the left side
|
||||||
|
*/
|
||||||
private void addInputRow(GridBagConstraints constraints, JComponent target, JComponent comp, int row, JLabel label) {
|
private void addInputRow(GridBagConstraints constraints, JComponent target, JComponent comp, int row, JLabel label) {
|
||||||
constraints.gridwidth = 1;
|
constraints.gridwidth = 1;
|
||||||
constraints.gridx = 1;
|
constraints.gridx = 1;
|
||||||
|
|
|
@ -5,7 +5,7 @@ import me.teridax.jcash.banking.Account;
|
||||||
public class DepositDialog {
|
public class DepositDialog {
|
||||||
|
|
||||||
public DepositDialog(Account account, Runnable onDeposit) {
|
public DepositDialog(Account account, Runnable onDeposit) {
|
||||||
var view = new DepositView(account);
|
var view = new DepositView();
|
||||||
view.getDeposit().addActionListener(e -> {
|
view.getDeposit().addActionListener(e -> {
|
||||||
account.deposit(view.getAmount());
|
account.deposit(view.getAmount());
|
||||||
onDeposit.run();
|
onDeposit.run();
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package me.teridax.jcash.gui.deposit;
|
package me.teridax.jcash.gui.deposit;
|
||||||
|
|
||||||
import me.teridax.jcash.banking.Account;
|
import me.teridax.jcash.banking.Account;
|
||||||
import me.teridax.jcash.decode.StringUtils;
|
import me.teridax.jcash.decode.StringDecoder;
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
|
@ -15,8 +15,8 @@ public class DepositView {
|
||||||
private JButton deposit;
|
private JButton deposit;
|
||||||
private JFormattedTextField value;
|
private JFormattedTextField value;
|
||||||
|
|
||||||
public DepositView(Account account) {
|
public DepositView() {
|
||||||
createComponents(account);
|
createComponents();
|
||||||
layoutComponents();
|
layoutComponents();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,12 +80,12 @@ public class DepositView {
|
||||||
dialog.getContentPane().add(buttonPanel, c);
|
dialog.getContentPane().add(buttonPanel, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createComponents(Account account) {
|
private void createComponents() {
|
||||||
this.dialog = new JDialog();
|
this.dialog = new JDialog();
|
||||||
|
|
||||||
this.cancel = new JButton("Cancel");
|
this.cancel = new JButton("Cancel");
|
||||||
this.deposit = new JButton("Deposit");
|
this.deposit = new JButton("Deposit");
|
||||||
this.value = new JFormattedTextField(StringUtils.LOCAL_NUMBER_FORMAT);
|
this.value = new JFormattedTextField(StringDecoder.LOCAL_NUMBER_FORMAT);
|
||||||
|
|
||||||
this.dialog.setContentPane(new JPanel(new GridBagLayout()));
|
this.dialog.setContentPane(new JPanel(new GridBagLayout()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,7 +2,15 @@ package me.teridax.jcash.gui.login;
|
||||||
|
|
||||||
import me.teridax.jcash.banking.Profile;
|
import me.teridax.jcash.banking.Profile;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Listens for changes in a selected account.
|
||||||
|
*/
|
||||||
public interface AccountSelectionListener {
|
public interface AccountSelectionListener {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run when a new account is selected.
|
||||||
|
* The selected account is set as the primary account of the profile
|
||||||
|
* @param account the profile for the selected account
|
||||||
|
*/
|
||||||
void onAccountSelected(Profile account);
|
void onAccountSelected(Profile account);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,9 @@ import javax.swing.*;
|
||||||
import java.awt.event.ActionEvent;
|
import java.awt.event.ActionEvent;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import static javax.swing.JOptionPane.ERROR_MESSAGE;
|
||||||
|
import static javax.swing.JOptionPane.showMessageDialog;
|
||||||
|
|
||||||
public class LoginController {
|
public class LoginController {
|
||||||
|
|
||||||
private final LoginView view;
|
private final LoginView view;
|
||||||
|
@ -46,12 +49,13 @@ public class LoginController {
|
||||||
var blz = this.view.getBlz().getText();
|
var blz = this.view.getBlz().getText();
|
||||||
var iban = this.getIban();
|
var iban = this.getIban();
|
||||||
if (iban.isEmpty()) {
|
if (iban.isEmpty()) {
|
||||||
JOptionPane.showMessageDialog(null, "invalid IBAN", "Faulty login attempt", JOptionPane.ERROR_MESSAGE);
|
showMessageDialog(null, "invalid IBAN", "Faulty login attempt", ERROR_MESSAGE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var pin = this.getPin();
|
var pin = this.getPin();
|
||||||
if (pin.isEmpty()) {
|
if (pin.isEmpty()) {
|
||||||
JOptionPane.showMessageDialog(null, "invalid pin", "Faulty login attempt", JOptionPane.ERROR_MESSAGE);
|
showMessageDialog(null, "invalid pin", "Faulty login attempt", ERROR_MESSAGE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,7 +63,7 @@ public class LoginController {
|
||||||
if (account.isPresent()) {
|
if (account.isPresent()) {
|
||||||
this.listener.onAccountSelected(account.get());
|
this.listener.onAccountSelected(account.get());
|
||||||
} else {
|
} else {
|
||||||
JOptionPane.showMessageDialog(null, "invalid login credentials", "Faulty login attempt", JOptionPane.ERROR_MESSAGE);
|
showMessageDialog(null, "invalid login credentials", "Faulty login attempt", ERROR_MESSAGE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,4 +74,8 @@ public class LoginController {
|
||||||
public LoginView getView() {
|
public LoginView getView() {
|
||||||
return view;
|
return view;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public LoginData getData() {
|
||||||
|
return data;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,9 @@ import me.teridax.jcash.banking.Profile;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wrapper class for a {@link me.teridax.jcash.banking.BankingManagementSystem}
|
||||||
|
*/
|
||||||
public class LoginData {
|
public class LoginData {
|
||||||
|
|
||||||
private final BankingManagementSystem bms;
|
private final BankingManagementSystem bms;
|
||||||
|
@ -13,6 +16,13 @@ public class LoginData {
|
||||||
this.bms = bms;
|
this.bms = bms;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* authenticate the specified account with the provided pin.
|
||||||
|
* @param blz the bank identifier
|
||||||
|
* @param iban the account identifier
|
||||||
|
* @param pin the pin for the account to authenticate with
|
||||||
|
* @return an optional wrapping the specified account if authentication was successful
|
||||||
|
*/
|
||||||
public Optional<Profile> authenticateAccount(String blz, int iban, int pin) {
|
public Optional<Profile> authenticateAccount(String blz, int iban, int pin) {
|
||||||
var optionalBank = bms.getBank(blz);
|
var optionalBank = bms.getBank(blz);
|
||||||
if (optionalBank.isEmpty())
|
if (optionalBank.isEmpty())
|
||||||
|
@ -21,4 +31,8 @@ public class LoginData {
|
||||||
var profile = optionalBank.get().getAccount(iban);
|
var profile = optionalBank.get().getAccount(iban);
|
||||||
return profile.filter(value -> value.getPrimaryAccount().getPin() == pin);
|
return profile.filter(value -> value.getPrimaryAccount().getPin() == pin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public BankingManagementSystem getBms() {
|
||||||
|
return bms;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,34 +7,32 @@ import java.text.NumberFormat;
|
||||||
|
|
||||||
public class LoginView extends JPanel {
|
public class LoginView extends JPanel {
|
||||||
|
|
||||||
private final JFormattedTextField blz;
|
private JFormattedTextField blz;
|
||||||
private final JFormattedTextField iban;
|
private JFormattedTextField iban;
|
||||||
private final JPasswordField pin;
|
private JPasswordField pin;
|
||||||
private final JButton login;
|
private JButton login;
|
||||||
|
|
||||||
public LoginView() {
|
public LoginView() {
|
||||||
this.blz = new JFormattedTextField("MA2424");
|
createComponents();
|
||||||
this.iban = new JFormattedTextField(getNumberFormat());
|
layoutComponents();
|
||||||
this.iban.setText("4711");
|
}
|
||||||
this.pin = new JPasswordField("1234");
|
|
||||||
this.login = new JButton("Login");
|
private void layoutComponents() {
|
||||||
|
var content = new JPanel(new GridBagLayout());
|
||||||
|
|
||||||
setLayout(new BorderLayout(16, 16));
|
|
||||||
var content = new JPanel();
|
|
||||||
this.setBorder(BorderFactory.createEmptyBorder(8,8,8,8));
|
this.setBorder(BorderFactory.createEmptyBorder(8,8,8,8));
|
||||||
add(new JScrollPane(content), BorderLayout.CENTER);
|
this.setLayout(new BorderLayout(16, 16));
|
||||||
add(new JLabel("Bankautomat"), BorderLayout.NORTH);
|
this.add(new JScrollPane(content), BorderLayout.CENTER);
|
||||||
|
this.add(new JLabel("Bankautomat"), BorderLayout.NORTH);
|
||||||
|
|
||||||
var layout = new GridBagLayout();
|
|
||||||
var constraints = new GridBagConstraints();
|
var constraints = new GridBagConstraints();
|
||||||
content.setLayout(layout);
|
|
||||||
|
|
||||||
constraints.gridwidth = 4;
|
constraints.gridwidth = 4;
|
||||||
constraints.insets = new Insets(12,12,12,12);
|
constraints.insets = new Insets(12,12,12,12);
|
||||||
|
|
||||||
addInputRow(constraints, content, blz, 1, "BLZ");
|
addInputRow(constraints, content, blz, 1, "BLZ");
|
||||||
addInputRow(constraints, content, iban, 2, "Kontonummer");
|
addInputRow(constraints, content, iban, 2, "IBAN");
|
||||||
addInputRow(constraints, content, pin, 3, "Passwort");
|
addInputRow(constraints, content, pin, 3, "PIN");
|
||||||
|
|
||||||
constraints.gridy = 4;
|
constraints.gridy = 4;
|
||||||
constraints.anchor = GridBagConstraints.PAGE_END;
|
constraints.anchor = GridBagConstraints.PAGE_END;
|
||||||
|
@ -44,6 +42,14 @@ public class LoginView extends JPanel {
|
||||||
content.add(login, constraints);
|
content.add(login, constraints);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void createComponents() {
|
||||||
|
this.blz = new JFormattedTextField("MA2424");
|
||||||
|
this.iban = new JFormattedTextField(getNumberFormat());
|
||||||
|
this.iban.setText("4711");
|
||||||
|
this.pin = new JPasswordField("1234");
|
||||||
|
this.login = new JButton("Login");
|
||||||
|
}
|
||||||
|
|
||||||
private NumberFormatter getNumberFormat() {
|
private NumberFormatter getNumberFormat() {
|
||||||
var format = NumberFormat.getIntegerInstance();
|
var format = NumberFormat.getIntegerInstance();
|
||||||
format.setGroupingUsed(false);
|
format.setGroupingUsed(false);
|
||||||
|
|
|
@ -5,7 +5,7 @@ import me.teridax.jcash.banking.Account;
|
||||||
public class TakeoffDialog {
|
public class TakeoffDialog {
|
||||||
|
|
||||||
public TakeoffDialog(Account account, Runnable onTakeoff) {
|
public TakeoffDialog(Account account, Runnable onTakeoff) {
|
||||||
var view = new TakeoffView(account);
|
var view = new TakeoffView();
|
||||||
view.getTakeoff().addActionListener(e -> {
|
view.getTakeoff().addActionListener(e -> {
|
||||||
account.takeoff(view.getAmount());
|
account.takeoff(view.getAmount());
|
||||||
onTakeoff.run();
|
onTakeoff.run();
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package me.teridax.jcash.gui.takeoff;
|
package me.teridax.jcash.gui.takeoff;
|
||||||
|
|
||||||
import me.teridax.jcash.banking.Account;
|
import me.teridax.jcash.decode.StringDecoder;
|
||||||
import me.teridax.jcash.decode.StringUtils;
|
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
|
@ -18,8 +17,8 @@ public class TakeoffView {
|
||||||
private JButton takeoff;
|
private JButton takeoff;
|
||||||
private JFormattedTextField value;
|
private JFormattedTextField value;
|
||||||
|
|
||||||
public TakeoffView(Account account) {
|
public TakeoffView() {
|
||||||
createComponents(account);
|
createComponents();
|
||||||
layoutComponents();
|
layoutComponents();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,12 +80,12 @@ public class TakeoffView {
|
||||||
dialog.getContentPane().add(buttonPanel, c);
|
dialog.getContentPane().add(buttonPanel, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createComponents(Account account) {
|
private void createComponents() {
|
||||||
this.dialog = new JDialog();
|
this.dialog = new JDialog();
|
||||||
|
|
||||||
this.cancel = new JButton("Cancel");
|
this.cancel = new JButton("Cancel");
|
||||||
this.takeoff = new JButton("Takeoff");
|
this.takeoff = new JButton("Takeoff");
|
||||||
this.value = new JFormattedTextField(StringUtils.LOCAL_NUMBER_FORMAT);
|
this.value = new JFormattedTextField(StringDecoder.LOCAL_NUMBER_FORMAT);
|
||||||
|
|
||||||
this.dialog.setContentPane(new JPanel(new GridBagLayout()));
|
this.dialog.setContentPane(new JPanel(new GridBagLayout()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,39 @@
|
||||||
|
package me.teridax.jcash.gui.transfer;
|
||||||
|
|
||||||
|
import me.teridax.jcash.banking.BankingManagementSystem;
|
||||||
|
import me.teridax.jcash.decode.StringDecoder;
|
||||||
|
|
||||||
|
public class TransferData {
|
||||||
|
|
||||||
|
private final BankingManagementSystem bms;
|
||||||
|
|
||||||
|
public TransferData(BankingManagementSystem bms) {
|
||||||
|
this.bms = bms;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Transfers a certain amount of money to the specified account of the specified bank
|
||||||
|
* @param amount the amount to transfer
|
||||||
|
* @param blz the bank that manages the account
|
||||||
|
* @param ibanString the internal bank account number to transfer money to
|
||||||
|
* @throws IllegalArgumentException if the bank or the account do not exist
|
||||||
|
*/
|
||||||
|
public void transferValue(double amount, String blz, String ibanString) throws IllegalArgumentException {
|
||||||
|
var bank = bms.getBank(blz);
|
||||||
|
if (bank.isEmpty())
|
||||||
|
throw new IllegalArgumentException("Bank not found: " + blz);
|
||||||
|
|
||||||
|
var iban = 0;
|
||||||
|
try {
|
||||||
|
iban = StringDecoder.decodeUniqueIdentificationNumber(ibanString);
|
||||||
|
} catch (Exception ex) {
|
||||||
|
throw new IllegalArgumentException("IBAN has invalid format: " + ibanString);
|
||||||
|
}
|
||||||
|
|
||||||
|
var account = bank.get().getAccount(iban);
|
||||||
|
if (account.isEmpty())
|
||||||
|
throw new IllegalArgumentException("Account not found: " + iban);
|
||||||
|
|
||||||
|
account.get().getPrimaryAccount().deposit(amount);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,15 +1,29 @@
|
||||||
package me.teridax.jcash.gui.transfer;
|
package me.teridax.jcash.gui.transfer;
|
||||||
|
|
||||||
import me.teridax.jcash.banking.Account;
|
import me.teridax.jcash.banking.Account;
|
||||||
|
import me.teridax.jcash.banking.BankingManagementSystem;
|
||||||
|
|
||||||
|
import javax.swing.*;
|
||||||
|
|
||||||
|
import static javax.swing.JOptionPane.ERROR_MESSAGE;
|
||||||
|
import static javax.swing.JOptionPane.showMessageDialog;
|
||||||
|
|
||||||
public class TransferDialog {
|
public class TransferDialog {
|
||||||
|
|
||||||
public TransferDialog(Account account, Runnable onDeposit) {
|
public TransferDialog(Account account, BankingManagementSystem bms, Runnable onDeposit) {
|
||||||
var view = new TransferView(account);
|
var view = new TransferView();
|
||||||
|
var data = new TransferData(bms);
|
||||||
view.getTransfer().addActionListener(e -> {
|
view.getTransfer().addActionListener(e -> {
|
||||||
account.takeoff(view.getAmount());
|
try {
|
||||||
|
var amount = view.getAmount();
|
||||||
|
|
||||||
|
data.transferValue(amount, view.getBlz(), view.getIban());
|
||||||
|
account.takeoff(amount);
|
||||||
onDeposit.run();
|
onDeposit.run();
|
||||||
view.dispose();
|
view.dispose();
|
||||||
|
} catch (IllegalArgumentException ex) {
|
||||||
|
showMessageDialog(null, "invalid account", "Could not transfer", ERROR_MESSAGE);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
view.getCancel().addActionListener(e -> view.dispose());
|
view.getCancel().addActionListener(e -> view.dispose());
|
||||||
view.showDialog();
|
view.showDialog();
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package me.teridax.jcash.gui.transfer;
|
package me.teridax.jcash.gui.transfer;
|
||||||
|
|
||||||
import me.teridax.jcash.banking.Account;
|
import me.teridax.jcash.decode.StringDecoder;
|
||||||
import me.teridax.jcash.decode.StringUtils;
|
|
||||||
|
|
||||||
import javax.swing.*;
|
import javax.swing.*;
|
||||||
import java.awt.*;
|
import java.awt.*;
|
||||||
|
@ -20,8 +19,8 @@ public class TransferView {
|
||||||
private JFormattedTextField blz;
|
private JFormattedTextField blz;
|
||||||
private JFormattedTextField value;
|
private JFormattedTextField value;
|
||||||
|
|
||||||
public TransferView(Account account) {
|
public TransferView() {
|
||||||
createComponents(account);
|
createComponents();
|
||||||
layoutComponents();
|
layoutComponents();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,12 +104,12 @@ public class TransferView {
|
||||||
dialog.getContentPane().add(buttonPanel, c);
|
dialog.getContentPane().add(buttonPanel, c);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void createComponents(Account account) {
|
private void createComponents() {
|
||||||
this.dialog = new JDialog();
|
this.dialog = new JDialog();
|
||||||
|
|
||||||
this.cancel = new JButton("Cancel");
|
this.cancel = new JButton("Cancel");
|
||||||
this.transfer = new JButton("Transfer");
|
this.transfer = new JButton("Transfer");
|
||||||
this.value = new JFormattedTextField(StringUtils.LOCAL_NUMBER_FORMAT);
|
this.value = new JFormattedTextField(StringDecoder.LOCAL_NUMBER_FORMAT);
|
||||||
this.iban = new JFormattedTextField();
|
this.iban = new JFormattedTextField();
|
||||||
this.blz = new JFormattedTextField();
|
this.blz = new JFormattedTextField();
|
||||||
|
|
||||||
|
@ -138,6 +137,14 @@ public class TransferView {
|
||||||
return transfer;
|
return transfer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getIban() {
|
||||||
|
return iban.getText();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBlz() {
|
||||||
|
return blz.getText();
|
||||||
|
}
|
||||||
|
|
||||||
public void dispose() {
|
public void dispose() {
|
||||||
this.dialog.dispose();
|
this.dialog.dispose();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue