commit ca2f056008b2db7a5aa1c802f90a46619c000523 Author: Safak Date: Sun Dec 1 01:19:55 2024 +0100 initial diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..5ff6309 --- /dev/null +++ b/.gitignore @@ -0,0 +1,38 @@ +target/ +!.mvn/wrapper/maven-wrapper.jar +!**/src/main/**/target/ +!**/src/test/**/target/ + +### IntelliJ IDEA ### +.idea/modules.xml +.idea/jarRepositories.xml +.idea/compiler.xml +.idea/libraries/ +*.iws +*.iml +*.ipr + +### Eclipse ### +.apt_generated +.classpath +.factorypath +.project +.settings +.springBeans +.sts4-cache + +### NetBeans ### +/nbproject/private/ +/nbbuild/ +/dist/ +/nbdist/ +/.nb-gradle/ +build/ +!**/src/main/**/build/ +!**/src/test/**/build/ + +### VS Code ### +.vscode/ + +### Mac OS ### +.DS_Store \ No newline at end of file diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..aa00ffa --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..e122dea --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,14 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/accountdata/Max.json b/accountdata/Max.json new file mode 100644 index 0000000..bc16387 --- /dev/null +++ b/accountdata/Max.json @@ -0,0 +1,32 @@ +[ + { + "CLASSNAME": "Payment", + "INSTANCE": { + "incomingInterest": 0.025, + "outgoingInterest": 0.05, + "date": "10.01.1988", + "amount": 1500, + "description": "Deposit; 1500" + } + }, + { + "CLASSNAME": "IncomingTransfer", + "INSTANCE": { + "sender": "Account Eva", + "recipient": "Account Adam", + "date": "01.01.2021", + "amount": 150, + "description": "Incoming Transfer; Eva->Adam; 150" + } + }, + { + "CLASSNAME": "OutgoingTransfer", + "INSTANCE": { + "sender": "Account Adam", + "recipient": "Account Eva", + "date": "03.01.2021", + "amount": 50, + "description": "Outgoing Transfer; Adam->Eva; 50" + } + } +] \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..1527790 --- /dev/null +++ b/pom.xml @@ -0,0 +1,60 @@ + + + P4 + de.fh_aachen.oos + 4.0.0 + 1.0-SNAPSHOT + + + + + maven-compiler-plugin + org.apache.maven.plugins + + + --release + 17 + + + 3.13.0 + + + maven-surefire-plugin + org.apache.maven.plugins + 3.2.5 + + + + + + + junit-jupiter + org.junit.jupiter + test + + + gson + com.google.code.gson + 2.11.0 + + + + + + + junit-bom + org.junit + import + pom + 5.11.3 + + + + + + 17 + UTF-8 + + \ No newline at end of file diff --git a/src/main/java/ClassDiagram.md b/src/main/java/ClassDiagram.md new file mode 100644 index 0000000..2dec80e --- /dev/null +++ b/src/main/java/ClassDiagram.md @@ -0,0 +1,141 @@ +```` mermaid +classDiagram + direction TB + + CalculateBill ..> Transaction + Transaction --> Transfer + Transaction --> Payment + Transfer --> IncomingTransfer + Transfer --> OutgoingTransfer + Bank ..> PrivateBank + PrivateBank "1" --> "n" Transaction + + class Transaction{ + <> + # date : String + # amount : double + # description : String + + getDate() String * + + setDate(nDt : String) void * + + getAmount() double * + + setAmount(nA : double) void * + + getDescription() String * + + setDescription(nDs : String) void * + + + calculate() double * + + toString() String * + + equals(o : Object) boolean * + + + Transaction(nDt : String, nA : double, nDs : String) * + } + + class Transfer{ + - sender : String + - recipient : String + + getSender() String + + setSender(nS : String) void + + getRecipient() String + + setRecipient(nR : String) void + + setAmount(nA : double) void + + + toString() String + + equals(o : Object) boolean + + + Transfer(nDt : String, nA : double, nDs : String) + + Transfer(nDt : String, nA : double, nDs : String, nS : String, nR : String) + + Transfer(t : Transfer) + } + + class IncomingTransfer{ + + IncomingTransfer(nDt : String, nA : double, nDs : String) void + + IncomingTransfer(nDt : String, nA : double, nDs : String, nS : String, nR : String) void + + IncomingTransfer(t : IncomingTransfer) void + + + calculate() double + + + deserialize(j : JsonElement, t : Type, c : JsonDeserializationContext) : Transaction + + serialize(t : Transaction, t : Type, c : JsonDeserializationContext) : void + } + + class OutgoingTransfer{ + + OutgoingTransfer(nDt : String, nA : double, nDs : String) + + OutgoingTransfer(nDt : String, nA : double, nDs : String, nS : String, nR : String) + + OutgoingTransfer(t : OutgoingTransfer) + + + calculate() double + + + deserialize(j : JsonElement, t : Type, c : JsonDeserializationContext) : Transaction + + serialize(t : Transaction, t : Type, c : JsonDeserializationContext) : void + } + + class Payment{ + - incommingInteres : double + - outgoingInterest : double + + getincommingInteres() double + + setincommingInteresr(nI : double) void + + getoutgoingInterest() double + + setoutgoingInterest(nO : double) void + + + calculate() double + + toString() String + + equals(o : Object) boolean + + + Transfer(nDt : String, nA : double, nDs : String) + + Transfer(nDt : String, nA : double, nDs : String, nI : double, nO : double) + + Transfer(p : Payment) + + + + deserialize(j : JsonElement, t : Type, c : JsonDeserializationContext) : Transaction + + serialize(t : Transaction, t : Type, c : JsonDeserializationContext) : void + } + + class CalculateBill{ + <> + + calculate() double + } + + class Bank{ + <> + + createAccount(nA : String) void + + createAccount(nA : String, t : List) void + + addTransaction(a : String, t : Transaction) void + + removeTransaction(a : String, t : Transaction) void + + getAccountBalance(a : String) double + + getTransactions(a : String) List + + getTransactionsSorted(a : String, asc : bool) List + + getTransactionsByType(a : String, pos : bool) List + } + + class PrivateBank{ + - name : String + - incomingInterest : double + - outgoingInterest : double + - directoryName : String + # accountsToTransactions : Map> + + + getName() String + + setName(nN : String) void + + getIncomingInterest() double + + setIncomingInterest(nI : double) void + + getOutgoingInterest() double + + setOutgoingnterest(nO : double) void + + getDirectoryName() String + + setDirectoryName(nD : String) void + + + PrivateBank(n : String, i : double, o : double, d : String) + + PrivateBank(b : PrivateBank) + + + toString() String + + equals(o : Object) boolean + + + createAccount(nA : String) void + + createAccount(nA : String, t : List) void + + addTransaction(a : String, t : Transaction) void + + removeTransaction(a : String, t : Transaction) void + + getAccountBalance(a : String) double + + getTransactions(a : String) List + + getTransactionsSorted(a : String, asc : bool) List + + getTransactionsByType(a : String, pos : bool) List + + } +```` \ No newline at end of file diff --git a/src/main/java/Main.java b/src/main/java/Main.java new file mode 100644 index 0000000..3cbc1d1 --- /dev/null +++ b/src/main/java/Main.java @@ -0,0 +1,314 @@ +import bank.*; +import bank.exceptions.IOException; +import bank.exceptions.TransactionAttributeException; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +public class Main { + private static void testingTransactions(Payment p1, Payment p2, Transfer t1, Transfer t2) throws TransactionAttributeException { + System.out.println("Basic Testcases------------------"); + + Payment p1c = new Payment(p1); + Payment p2c = new Payment(p2); + + System.out.print(p1); + System.out.print(p2); + System.out.print(p1c); + System.out.print(p2c); + + Transfer t1c = new Transfer(t1); + Transfer t2c = new Transfer(t2); + + System.out.print(t1); + System.out.print(t2); + System.out.print(t1c); + System.out.print(t2c); + + System.out.println("\nTest Edgecases-----------------"); + + setInterestRateCatch(p2, -0.5); + setInterestRateCatch(p2, 1.5); + + setAmountCatch(t1, -5); + + System.out.println("\nCompare Payments--------------"); + System.out.println(p1.equals(p1c)); + System.out.println(p1.equals(p2)); + + System.out.println(p1.equals(new ArrayList<>())); + System.out.println(p1.equals(null)); + + System.out.println("\nCompare Transfers-------------"); + System.out.println(t1.equals(t1c)); + System.out.println(t1.equals(t2)); + + + } + + private static void testingBankWithTransactions(Transaction t1, Transaction t2, Transaction t3, Transaction t4, PrivateBank bank, String person) { + // ------------------------ Bank: Adding Payments + + if(t1 instanceof Payment){ + System.out.println("\n------------------------ Bank: Adding Payment"); + System.out.println("p1 IncIntr. before adding : 0.0 = " + ((Payment) t1).getIncomingInterest()); + System.out.println("p1 OutIntr. before adding : 0.0 = " + ((Payment) t1).getOutgoingInterest()); + System.out.println("p2 IncIntr. before adding : 0.0 = " + ((Payment) t2).getIncomingInterest()); + System.out.println("p2 OutIntr. before adding : 0.0 = " + ((Payment) t2).getOutgoingInterest()); + System.out.println("p3 IncIntr. before adding : 0.5 = " + ((Payment) t3).getIncomingInterest()); + System.out.println("p3 OutIntr. before adding : 0.0 = " + ((Payment) t3).getOutgoingInterest()); + System.out.println("p4 IncIntr. before adding : 0.0 = " + ((Payment) t4).getIncomingInterest()); + System.out.println("p4 OutIntr. before adding : 0.25= " + ((Payment) t4).getOutgoingInterest()); + } + else if(t1 instanceof IncomingTransfer){ + System.out.println("\n------------------------ Bank: Adding IncomingTransfer"); + System.out.println("t1 Sender before adding : = " + ((IncomingTransfer) t1).getSender()); + System.out.println("t1 Recipient before adding : = " + ((IncomingTransfer) t1).getRecipient()); + System.out.println("t2 Sender before adding : Mustermann = " + ((IncomingTransfer) t2).getSender()); + System.out.println("t2 Recipient before adding : Musterfrau = " + ((IncomingTransfer) t2).getRecipient()); + System.out.println("t3 Sender before adding : Max Mustermann = " + ((IncomingTransfer) t3).getSender()); + System.out.println("t3 Recipient before adding : Maria Musterfrau = " + ((IncomingTransfer) t3).getRecipient()); + System.out.println("t4 Sender before adding : Maria Musterfrau = " + ((IncomingTransfer) t4).getSender()); + System.out.println("t4 Recipient before adding : Max Musterman = " + ((IncomingTransfer) t4).getRecipient()); + } + else if(t1 instanceof OutgoingTransfer){ + System.out.println("\n------------------------ Bank: Adding OutgoingTransfer"); + System.out.println("t1 Sender before adding : = " + ((OutgoingTransfer) t1).getSender()); + System.out.println("t1 Recipient before adding : = " + ((OutgoingTransfer) t1).getRecipient()); + System.out.println("t2 Sender before adding : Mustermann = " + ((OutgoingTransfer) t2).getSender()); + System.out.println("t2 Recipient before adding : Musterfrau = " + ((OutgoingTransfer) t2).getRecipient()); + System.out.println("t3 Sender before adding : Max Mustermann = " + ((OutgoingTransfer) t3).getSender()); + System.out.println("t3 Recipient before adding : Maria Musterfrau = " + ((OutgoingTransfer) t3).getRecipient()); + System.out.println("t4 Sender before adding : Maria Musterfrau = " + ((OutgoingTransfer) t4).getSender()); + System.out.println("t4 Recipient before adding : Max Musterman = " + ((OutgoingTransfer) t4).getRecipient()); + } + + addingTransactionCatch(bank, person, t1); + addingTransactionCatch(bank, person, t1); + addingTransactionCatch(bank, person, t2); + addingTransactionCatch(bank, person, t3); + addingTransactionCatch(bank, person, t4); + + System.out.println("\n------------------------ Bank: Printing Transactions"); + List p = bank.getTransactions(person); + p.forEach(System.out::println); + + System.out.println("\n------------------------ Bank: Printing Balance"); + double balanceP1 = bank.getAccountBalance(person); + System.out.println("balance of Person1 " + person + " = " + balanceP1); + System.out.println("Payment = -15; Outgoing = -12.5; Incoming = 5"); + + + System.out.println("\n------------------------ Bank: Removing Transaction"); + + removingTransactionCatch(bank, person, t1); + removingTransactionCatch(bank, person, t1); + removingTransactionCatch(bank, person, t2); + removingTransactionCatch(bank, person, t3); + removingTransactionCatch(bank, person, t4); + + + System.out.println("\n------------------------ Bank: Printing Transactions"); + p = bank.getTransactions(person); + p.forEach(System.out::println); + + System.out.println("\n------------------------ Bank: Printing Balance"); + balanceP1 = bank.getAccountBalance(person); + System.out.println("balance of Person1 " + person + " 0 = " + balanceP1); + } + + /* + private static void testingBankWithListOfTransactions(List transactions, PrivateBank bank, String person) { + // ------------------------ Bank: Adding Payments + + if(transactions.getFirst() instanceof Payment){ + System.out.println("\n------------------------ Bank: Adding Payment"); + System.out.println("p1 IncIntr. before adding : 0.0 = " + ((Payment) transactions.get(0)).getIncomingInterest()); + System.out.println("p1 OutIntr. before adding : 0.0 = " + ((Payment) transactions.get(0)).getOutgoingInterest()); + System.out.println("p2 IncIntr. before adding : 0.0 = " + ((Payment) transactions.get(1)).getIncomingInterest()); + System.out.println("p2 OutIntr. before adding : 0.0 = " + ((Payment) transactions.get(1)).getOutgoingInterest()); + System.out.println("p3 IncIntr. before adding : 0.5 = " + ((Payment) transactions.get(2)).getIncomingInterest()); + System.out.println("p3 OutIntr. before adding : 0.0 = " + ((Payment) transactions.get(2)).getOutgoingInterest()); + System.out.println("p4 IncIntr. before adding : 0.0 = " + ((Payment) transactions.get(3)).getIncomingInterest()); + System.out.println("p4 OutIntr. before adding : 0.25= " + ((Payment) transactions.get(3)).getOutgoingInterest()); + } + else if(transactions.getFirst() instanceof IncomingTransfer){ + System.out.println("\n------------------------ Bank: Adding IncomingTransfer"); + System.out.println("t1 Sender before adding : = " + ((IncomingTransfer) transactions.get(0)).getSender()); + System.out.println("t1 Recipient before adding : = " + ((IncomingTransfer) transactions.get(0)).getRecipient()); + System.out.println("t2 Sender before adding : Mustermann = " + ((IncomingTransfer) transactions.get(1)).getSender()); + System.out.println("t2 Recipient before adding : Musterfrau = " + ((IncomingTransfer) transactions.get(1)).getRecipient()); + System.out.println("t3 Sender before adding : Max Mustermann = " + ((IncomingTransfer) transactions.get(2)).getSender()); + System.out.println("t3 Recipient before adding : Maria Musterfrau = " + ((IncomingTransfer) transactions.get(2)).getRecipient()); + System.out.println("t4 Sender before adding : Maria Musterfrau = " + ((IncomingTransfer) transactions.get(3)).getSender()); + System.out.println("t4 Recipient before adding : Max Musterman = " + ((IncomingTransfer) transactions.get(3)).getRecipient()); + } + else if(transactions.getFirst() instanceof OutgoingTransfer){ + System.out.println("\n------------------------ Bank: Adding OutgoingTransfer"); + System.out.println("t1 Sender before adding : = " + ((OutgoingTransfer) transactions.get(0)).getSender()); + System.out.println("t1 Recipient before adding : = " + ((OutgoingTransfer) transactions.get(0)).getRecipient()); + System.out.println("t2 Sender before adding : Mustermann = " + ((OutgoingTransfer) transactions.get(1)).getSender()); + System.out.println("t2 Recipient before adding : Musterfrau = " + ((OutgoingTransfer) transactions.get(1)).getRecipient()); + System.out.println("t3 Sender before adding : Max Mustermann = " + ((OutgoingTransfer) transactions.get(2)).getSender()); + System.out.println("t3 Recipient before adding : Maria Musterfrau = " + ((OutgoingTransfer) transactions.get(2)).getRecipient()); + System.out.println("t4 Sender before adding : Maria Musterfrau = " + ((OutgoingTransfer) transactions.get(3)).getSender()); + System.out.println("t4 Recipient before adding : Max Musterman = " + ((OutgoingTransfer) transactions.get(3)).getRecipient()); + } + + + addingTransactionCatch(bank, person, t1); + addingTransactionCatch(bank, person, t1); + addingTransactionCatch(bank, person, t2); + addingTransactionCatch(bank, person, t3); + addingTransactionCatch(bank, person, t4); + + System.out.println("\n------------------------ Bank: Printing Transactions"); + List p = bank.getTransactions(person); + p.forEach(System.out::println); + + System.out.println("\n------------------------ Bank: Printing Balance"); + double balanceP1 = bank.getAccountBalance(person); + System.out.println("balance of Person1 " + person + " = " + balanceP1); + System.out.println("Payment = -15; Outgoing = -12.5; Incoming = 5"); + + + System.out.println("\n------------------------ Bank: Removing Transaction"); + + removingTransactionCatch(bank, person, t1); + removingTransactionCatch(bank, person, t1); + removingTransactionCatch(bank, person, t2); + removingTransactionCatch(bank, person, t3); + removingTransactionCatch(bank, person, t4); + + + System.out.println("\n------------------------ Bank: Printing Transactions"); + p = bank.getTransactions(person); + p.forEach(System.out::println); + + System.out.println("\n------------------------ Bank: Printing Balance"); + balanceP1 = bank.getAccountBalance(person); + System.out.println("balance of Person1 " + person + " 0 = " + balanceP1); + } + + */ + // ------------------------ Catch-Helper ------------------------ + + private static void accountCreationCatch(Bank bank, String account){ + try { + bank.createAccount(account); + } catch (Exception e) { + System.out.println(e); + } + } + + private static void accountCreationWihtListCatch(Bank bank, String account, List transactions){ + try { + bank.createAccount(account, transactions); + } catch (Exception e) { + System.out.println(e); + } + } + + private static void setInterestRateCatch(Payment p, double interestrate) { + try { + p.setIncomingInterest(interestrate); + } catch (Exception e) { + System.out.println(e); + } + try { + p.setOutgoingInterest(interestrate); + } catch (Exception e) { + System.out.println(e); + } + } + + private static void setAmountCatch(Transaction t, double amount) { + try { + t.setAmount(amount); + } catch (Exception e) { + System.out.println(e); + } + } + + private static void addingTransactionCatch(Bank bank, String person, Transaction transaction) { + try { + bank.addTransaction(person, transaction); + } catch (Exception e) { + System.out.println(e); + } + } + + + private static void removingTransactionCatch(Bank bank, String person, Transaction transaction) { + try { + bank.removeTransaction(person, transaction); + } catch (Exception e) { + System.out.println(e); + } + } + + + // ------------------------ MAIN ------------------------ + + public static void main(String[] args) throws TransactionAttributeException, IOException, java.io.IOException { + String person1 = "Max Mustermann"; + String person2 = "Maria Musterfrau"; + String person3 = "Tom Mustermann"; + String person4 = "Hannah Musterfrau"; + + // ------------------------ Transactions ------------------------ + + /* + Payment p1 = new Payment("01.01.24", 10, "Verwendungszweck P1"); + Payment p2 = new Payment("01.01.24", 10, "Verwendungszweck P2", 0, 0); + Payment p3 = new Payment("01.01.24", -10, "Verwendungszweck P3", 0.5, 0); + Payment p4 = new Payment("01.01.24", -10, "Verwendungszweck P4", 0, 0.25); + + Transfer t1 = new Transfer("01.01.24", 10, "Verwendungszweck T1"); + Transfer t2 = new Transfer("01.01.24", 10, "Verwendungszweck T2", "Mustermann", "Musterfrau"); + Transfer t3 = new Transfer("01.01.24", 10, "Verwendungszweck T3", person1, person2); + Transfer t4 = new Transfer("01.01.24", 10, "Verwendungszweck T4", person2, person1); + Transfer t5 = new Transfer("01.01.24", 15, "Verwendungszweck T5", person2, person3); + Transfer t6 = new Transfer("01.01.24", 20, "Verwendungszweck T6", person2, person4); + + + IncomingTransfer it1 = new IncomingTransfer(t1.getDate(), t1.getAmount(), t1.getDescription()); + IncomingTransfer it2 = new IncomingTransfer(t2.getDate(), t2.getAmount(), t2.getDescription(), person2, person1); + IncomingTransfer it3 = new IncomingTransfer(t3.getDate(), t3.getAmount(), t3.getDescription(), person3, person1); + IncomingTransfer it4 = new IncomingTransfer(t4.getDate(), t4.getAmount(), t4.getDescription(), person4, person1); + IncomingTransfer it5 = new IncomingTransfer(t5.getDate(), t5.getAmount(), t5.getDescription(), person4, person1); + IncomingTransfer it6 = new IncomingTransfer(t6.getDate(), t6.getAmount(), t6.getDescription(), person3, person1); + + OutgoingTransfer ot1 = new OutgoingTransfer(t1.getDate(), t1.getAmount(), t1.getDescription()); + OutgoingTransfer ot2 = new OutgoingTransfer(t2.getDate(), t2.getAmount(), t2.getDescription(), person2, person1); + OutgoingTransfer ot3 = new OutgoingTransfer(t3.getDate(), t3.getAmount(), t3.getDescription(), person2, person1); + OutgoingTransfer ot4 = new OutgoingTransfer(t4.getDate(), t4.getAmount(), t4.getDescription(), person2, person3); + OutgoingTransfer ot5 = new OutgoingTransfer(t5.getDate(), t5.getAmount(), t5.getDescription(), person2, person3); + OutgoingTransfer ot6 = new OutgoingTransfer(t6.getDate(), t6.getAmount(), t6.getDescription(), person2, person4); + + List paymentsList = new ArrayList<>(Arrays.asList(p1, p2, p3, p4)); + List incomingTransfersList = new ArrayList<>(Arrays.asList(it2, it3, it4, it5, it6)); + List outgoingTransferList = new ArrayList<>(Arrays.asList(ot2, ot3, ot4, ot5, ot6)); + List incomingTransfersListWrong = new ArrayList<>(Arrays.asList(it1, it2, it3, it4, it5, it6)); + List outgoingTransferListWrong = new ArrayList<>(Arrays.asList(ot1, ot2, ot3, ot4, ot5, ot6)); + + testingTransactions(p1, p2, t1, t2); + + */ + + // ------------------------ Bank ------------------------ + + System.out.println("\n------------------------ Bank"); + PrivateBank bank = new PrivateBank("Sparkasse", 0.5, 0.25,"accountdata"); + PrivateBankAlt bankAlt = new PrivateBankAlt("SparkasseAlt", 0.5, 0.25); + PrivateBank bank1 = new PrivateBank("Commerzbank", 0.5, 0.25,"accountdata"); + + // ------------------------ Bank: Adding Accounts + + bank.readAccounts(); + + } + + +} \ No newline at end of file diff --git a/src/main/java/bank/Bank.java b/src/main/java/bank/Bank.java new file mode 100644 index 0000000..6aa3867 --- /dev/null +++ b/src/main/java/bank/Bank.java @@ -0,0 +1,100 @@ +package bank; + +import bank.exceptions.*; + +import java.util.List; + +/** + * Interface for a generic bank. Provides multiple methods to handle the interaction between + * accounts and transactions. + */ +public interface Bank { + + /** + * Adds an account to the bank. + * + * @param account the account to be added + * @throws AccountAlreadyExistsException if the account already exists + */ + void createAccount(String account) throws AccountAlreadyExistsException; + + /** + * Adds an account (with specified transactions) to the bank. + * Important: duplicate transactions must not be added to the account! + * + * @param account the account to be added + * @param transactions a list of already existing transactions which should be added to the newly created account + * @throws AccountAlreadyExistsException if the account already exists + * @throws TransactionAlreadyExistException if the transaction already exists + * @throws TransactionAttributeException if the validation check for certain attributes fail + */ + void createAccount(String account, List transactions) + throws AccountAlreadyExistsException, TransactionAlreadyExistException, TransactionAttributeException; + + /** + * Adds a transaction to an already existing account. + * + * @param account the account to which the transaction is added + * @param transaction the transaction which should be added to the specified account + * @throws TransactionAlreadyExistException if the transaction already exists + * @throws AccountDoesNotExistException if the specified account does not exist + * @throws TransactionAttributeException if the validation check for certain attributes fail + */ + void addTransaction(String account, Transaction transaction) + throws TransactionAlreadyExistException, AccountDoesNotExistException, TransactionAttributeException, IOException; + + /** + * Removes a transaction from an account. If the transaction does not exist, an exception is + * thrown. + * + * @param account the account from which the transaction is removed + * @param transaction the transaction which is removed from the specified account + * @throws AccountDoesNotExistException if the specified account does not exist + * @throws TransactionDoesNotExistException if the transaction cannot be found + */ + void removeTransaction(String account, Transaction transaction) + throws AccountDoesNotExistException, TransactionDoesNotExistException, IOException; + + /** + * Checks whether the specified transaction for a given account exists. + * + * @param account the account from which the transaction is checked + * @param transaction the transaction to search/look for + */ + boolean containsTransaction(String account, Transaction transaction); + + /** + * Calculates and returns the current account balance. + * + * @param account the selected account + * @return the current account balance + */ + double getAccountBalance(String account); + + /** + * Returns a list of transactions for an account. + * + * @param account the selected account + * @return the list of all transactions for the specified account + */ + List getTransactions(String account); + + /** + * Returns a sorted list (-> calculated amounts) of transactions for a specific account. Sorts the list either in ascending or descending order + * (or empty). + * + * @param account the selected account + * @param asc selects if the transaction list is sorted in ascending or descending order + * @return the sorted list of all transactions for the specified account + */ + List getTransactionsSorted(String account, boolean asc); + + /** + * Returns a list of either positive or negative transactions (-> calculated amounts). + * + * @param account the selected account + * @param positive selects if positive or negative transactions are listed + * @return the list of all transactions by type + */ + List getTransactionsByType(String account, boolean positive); +} diff --git a/src/main/java/bank/CalculateBill.java b/src/main/java/bank/CalculateBill.java new file mode 100644 index 0000000..cb2f626 --- /dev/null +++ b/src/main/java/bank/CalculateBill.java @@ -0,0 +1,5 @@ +package bank; + +public interface CalculateBill { + double calculate(); +} diff --git a/src/main/java/bank/IncomingTransfer.java b/src/main/java/bank/IncomingTransfer.java new file mode 100644 index 0000000..3229701 --- /dev/null +++ b/src/main/java/bank/IncomingTransfer.java @@ -0,0 +1,42 @@ +package bank; + +import bank.exceptions.TransactionAttributeException; +import com.google.gson.*; + +import java.lang.reflect.Type; + +public class IncomingTransfer extends Transfer { + + /** + * Constructor for creating a transfer with date, amount, and description + * based on abstract class + * + * @param newDate The date of the transfer. + * @param newAmount The amount of the transfer. + * @param newDescription The description of the transfer. + */ + public IncomingTransfer(String newDate, double newAmount, String newDescription) throws TransactionAttributeException { + super(newDate, newAmount, newDescription); + } + + + /** + * Constructor for creating a transfer with date, amount, and description + * based on abstract class + * + * @param newDate The date of the transfer. + * @param newAmount The amount of the transfer. + * @param newDescription The description of the transfer. + * @param newSender + * @param newRecipient + */ + public IncomingTransfer(String newDate, double newAmount, String newDescription, String newSender, String newRecipient) throws TransactionAttributeException { + super(newDate, newAmount, newDescription, newSender, newRecipient); + } + + @Override + public double calculate() { + return this.getAmount(); + } + +} diff --git a/src/main/java/bank/OutgoingTransfer.java b/src/main/java/bank/OutgoingTransfer.java new file mode 100644 index 0000000..dd44af3 --- /dev/null +++ b/src/main/java/bank/OutgoingTransfer.java @@ -0,0 +1,43 @@ +package bank; + +import bank.exceptions.TransactionAttributeException; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonElement; +import com.google.gson.JsonParseException; +import com.google.gson.JsonSerializationContext; + +import java.lang.reflect.Type; + +public class OutgoingTransfer extends Transfer { + + /** + * Constructor for creating a transfer with date, amount, and description + * based on abstract class + * + * @param newDate The date of the transfer. + * @param newAmount The amount of the transfer. + * @param newDescription The description of the transfer. + */ + public OutgoingTransfer(String newDate, double newAmount, String newDescription) throws TransactionAttributeException { + super(newDate, newAmount, newDescription); + } + + /** + * Constructor for creating a transfer with date, amount, and description + * based on abstract class + * + * @param newDate The date of the transfer. + * @param newAmount The amount of the transfer. + * @param newDescription The description of the transfer. + * @param newSender + * @param newRecipient + */ + public OutgoingTransfer(String newDate, double newAmount, String newDescription, String newSender, String newRecipient) throws TransactionAttributeException { + super(newDate, newAmount, newDescription, newSender, newRecipient); + } + + @Override + public double calculate() { + return this.getAmount() * (-1); + } +} diff --git a/src/main/java/bank/Payment.java b/src/main/java/bank/Payment.java new file mode 100644 index 0000000..48c0ec3 --- /dev/null +++ b/src/main/java/bank/Payment.java @@ -0,0 +1,150 @@ +package bank; + +import bank.exceptions.TransactionAttributeException; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonElement; +import com.google.gson.JsonParseException; +import com.google.gson.JsonSerializationContext; + +import java.lang.reflect.Type; + +/** + * The Payment class represents a payment with a date, amount, description, + * and optional incoming and outgoing interest rates. + */ +public class Payment extends Transaction { + /** + * private variables + */ + private double incomingInterest; + private double outgoingInterest; + + /** + * Sets the incoming interest rate for the payment. + * The value must be between 0 and 1. + * + * @param newIncomingInterest The new incoming interest rate. + */ + public void setIncomingInterest(double newIncomingInterest) throws TransactionAttributeException { + if (newIncomingInterest >= 0 && newIncomingInterest <= 1) + this.incomingInterest = newIncomingInterest; + else + throw new TransactionAttributeException("incoming interest must be between 0 and 1"); + } + + /** + * Gets the incoming interest rate for the payment. + * + * @return The incoming interest rate. + */ + public double getIncomingInterest() { + return incomingInterest; + } + + /** + * Sets the outgoing interest rate for the payment. + * The value must be between 0 and 1. + * + * @param newOutgoingInterest The new outgoing interest rate. + */ + public void setOutgoingInterest(double newOutgoingInterest) throws TransactionAttributeException { + if (newOutgoingInterest >= 0 && newOutgoingInterest <= 1) + this.outgoingInterest = newOutgoingInterest; + else + throw new TransactionAttributeException("outgoing interest must be between 0 and 1"); + } + + /** + * Gets the outgoing interest rate for the payment. + * + * @return The outgoing interest rate. + */ + public double getOutgoingInterest() { + return outgoingInterest; + } + + /** + * Constructor for creating a payment with date, amount, and description. + * + * @param newDate The date of the payment. + * @param newAmount The amount of the payment. + * @param newDescription The description of the payment. + */ + public Payment(String newDate, double newAmount, String newDescription) throws TransactionAttributeException { + super(newDate, newAmount, newDescription); + } + + /** + * Constructor for creating a payment with date, amount, description, + * and incoming and outgoing interest rates. + * + * @param newDate The date of the payment. + * @param newAmount The amount of the payment. + * @param newDescription The description of the payment. + * @param newIncomingInterest The incoming interest rate. + * @param newOutgoingInterest The outgoing interest rate. + */ + public Payment(String newDate, double newAmount, String newDescription, double newIncomingInterest, double newOutgoingInterest) throws TransactionAttributeException { + super(newDate, newAmount, newDescription); + this.setIncomingInterest(newIncomingInterest); + this.setOutgoingInterest(newOutgoingInterest); + } + + /** + * Copy constructor to create a new Payment object based on an existing one. + * + * @param p The Payment object to copy from. + */ + public Payment(Payment p) throws TransactionAttributeException { + this(p.getDate(), p.getAmount(), p.getDescription(), p.getIncomingInterest(), p.getOutgoingInterest()); + } + + @Override + public double calculate() { + // Incoming Amount + if (this.getAmount() > 0) { + // amount * ( 1 - incmInt ) + return (this.getAmount() * (1 - this.getIncomingInterest())); + } + // Outgoing Amount + else if (this.getAmount() < 0) { + // amount * ( 1 + outgInt ) + return (this.getAmount() * (1 + this.getOutgoingInterest())); + } + + // amount = 0 + return this.getAmount(); + } + + /** + * Prints the payment details to the console. + */ + @Override + public String toString() { + return ("\n------------Payment------------" + + super.toString() + + "\nIncomingInt: " + this.getIncomingInterest() + + "\nOutgoingInt: " + this.getOutgoingInterest() + + "\n-------------------------------\n" + ); + } + + /** + * Compares obj with current transaction + * + * @param obj The object to compare with + * @return Result of the comparison + */ + @Override + public boolean equals(Object obj) { + if (obj instanceof Payment) { + Payment p = (Payment) obj; + return( + super.equals(p) && + (this.getIncomingInterest() == p.getIncomingInterest()) && + (this.getOutgoingInterest() == p.getOutgoingInterest()) + ); + } + return false; + } +} diff --git a/src/main/java/bank/PrivateBank.java b/src/main/java/bank/PrivateBank.java new file mode 100644 index 0000000..aa6d1d1 --- /dev/null +++ b/src/main/java/bank/PrivateBank.java @@ -0,0 +1,435 @@ +package bank; + +import bank.exceptions.*; + +import java.lang.reflect.Type; +import java.util.*; +import java.nio.file.*; +import java.io.File; +import com.google.gson.*; + + +public class PrivateBank implements Bank, JsonSerializer, JsonDeserializer { + private String name; + private String directoryName; + private double incomingInterest; + private double outgoingInterest; + protected Map> accountsToTransactions = new HashMap<>(); + + /** + * @return Name of the Bank + */ + public String getName() { + return name; + } + + /** + * Sets the Name of the Bank + * + * @param newName Name + */ + public void setName(String newName) { + this.name = newName; + } + + /** + * @return IncomingInterest + */ + public double getIncomingInterest() { + return incomingInterest; + } + + /** + * Sets the IncomingInterest + * + * @param newIncomingInterest IncomingInterest + */ + public void setIncomingInterest(double newIncomingInterest) { + this.incomingInterest = newIncomingInterest; + } + + /** + * @return OutgoingInterest + */ + public double getOutgoingInterest() { + return outgoingInterest; + } + + /** + * Sets OutgoingInterest + * + * @param newOutgoingInterest OutgoingInterest + */ + public void setOutgoingInterest(double newOutgoingInterest) { + this.outgoingInterest = newOutgoingInterest; + } + + /** + * Sets DirectoryName + * @param newDirectoryName DirectoryName + */ + public void setDirectoryName(String newDirectoryName) { + this.directoryName = newDirectoryName; + } + + /** + * Returns DirectoryName + * @return DirectoryName + */ + public String getDirectoryName() { + return directoryName; + } + + /** + * Default Constructor + * + * @param name Name + * @param incomingInterest incoming Interest + * @param outgoingInterest outgoing Interest + */ + public PrivateBank(String name, double incomingInterest, double outgoingInterest, String directoryName) { + this.setName(name); + this.setIncomingInterest(incomingInterest); + this.setOutgoingInterest(outgoingInterest); + this.setDirectoryName(directoryName); + } + + /** + * Copy Constructor + * + * @param privateBank Bank to copy from + */ + public PrivateBank(PrivateBank privateBank) { + this.setName(privateBank.getName()); + this.setIncomingInterest(privateBank.getIncomingInterest()); + this.setOutgoingInterest(privateBank.getOutgoingInterest()); + this.setDirectoryName(privateBank.getDirectoryName()); + this.accountsToTransactions = privateBank.accountsToTransactions; + } + + @Override + public String toString() { + return ("\n--------------Bank-------------" + + "\n Name: " + this.getName() + + "\nIncomingInt: " + this.getIncomingInterest() + + "\nOutgoingInt: " + this.getOutgoingInterest() + + "\n-------------------------------\n" + ); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof PrivateBank) { + PrivateBank privateBank = (PrivateBank) obj; + return this.getName().equals(privateBank.getName()) && + this.getIncomingInterest() == privateBank.getIncomingInterest() && + this.getOutgoingInterest() == privateBank.getOutgoingInterest() && + // Compares the values in the maps and not if the objects are the same + this.accountsToTransactions.equals(privateBank.accountsToTransactions); + } + return false; + } + + /** + * Adds an account to the bank. + * + * @param account the account to be added + * @throws AccountAlreadyExistsException if the account already exists + */ + @Override + public void createAccount(String account) throws AccountAlreadyExistsException { + if (this.accountsToTransactions.containsKey(account)) { + throw new AccountAlreadyExistsException(); + } else { + List transactions = new ArrayList<>(); + this.accountsToTransactions.put(account, transactions); + } + + } + + /** + * Adds an account (with specified transactions) to the bank. + * Important: duplicate transactions must not be added to the account! + * + * @param account the account to be added + * @param transactions a list of already existing transactions which should be added to the newly created account + * @throws AccountAlreadyExistsException if the account already exists + * @throws TransactionAlreadyExistException if the transaction already exists + * @throws TransactionAttributeException if the validation check for certain attributes fail + */ + + @Override + public void createAccount(String account, List transactions) throws AccountAlreadyExistsException, TransactionAlreadyExistException, TransactionAttributeException { + createAccount(account); + for (Transaction transaction : transactions) { + if (this.accountsToTransactions.get(account).contains(transaction)) + throw new TransactionAlreadyExistException(); + else if (checkTransactionAttributes(account, transaction)) + this.accountsToTransactions.get(account).add(transaction); + } + } + + /** + * Adds a transaction to an already existing account. + * + * @param account the account to which the transaction is added + * @param transaction the transaction which should be added to the specified account + * @throws TransactionAlreadyExistException if the transaction already exists + * @throws AccountDoesNotExistException if the specified account does not exist + * @throws TransactionAttributeException if the validation check for certain attributes fail + */ + @Override + public void addTransaction(String account, Transaction transaction) throws TransactionAlreadyExistException, AccountDoesNotExistException, TransactionAttributeException, IOException { + // 1. check if Account exists + if (this.containsAccount(account)) { + // 2. check if Transaction exists + if (this.containsTransaction(account, transaction)) + throw new TransactionAlreadyExistException(); + else if (checkTransactionAttributes(account, transaction)){ + this.accountsToTransactions.get(account).add(transaction); + // 3. rewrite account because of change + writeAccount(account); + } + + + } else { + throw new AccountDoesNotExistException(); + } + } + + /** + * Checking transaction to be added, if they contain all necessary and correct Attributes + * + * @param account account holder name + * @param transaction transaction + * @throws TransactionAttributeException if the validation check for certain attributes fail + */ + private boolean checkTransactionAttributes(String account, Transaction transaction) throws TransactionAttributeException { + // 1 Overwriting interest values if it is a payment + if (transaction instanceof Payment) { + ((Payment) transaction).setIncomingInterest(this.getIncomingInterest()); + ((Payment) transaction).setOutgoingInterest(this.getOutgoingInterest()); + return true; + } + + // 2 setting as incoming transfer + else if (transaction instanceof IncomingTransfer) { + if (((IncomingTransfer) transaction).getSender().equals("") || ((IncomingTransfer) transaction).getRecipient().equals("")) + throw new TransactionAttributeException("Transfer without sender or recipient"); + + else if (((IncomingTransfer) transaction).getRecipient().equals(account)) + return true; + else + throw new TransactionAttributeException("Transfer recipient is not account holder"); + } + + // 3 setting as outgoing transfer + else if (transaction instanceof OutgoingTransfer) { + if (((OutgoingTransfer) transaction).getSender().equals("") || ((OutgoingTransfer) transaction).getRecipient().equals("")) + throw new TransactionAttributeException("Transfer without sender or recipient"); + + else if (((OutgoingTransfer) transaction).getSender().equals(account)) + return true; + else + throw new TransactionAttributeException("Transfer sender is not account holder "); + } + return false; + } + + /** + * Removes a transaction from an account. If the transaction does not exist, an exception is + * thrown. + * + * @param account the account from which the transaction is removed + * @param transaction the transaction which is removed from the specified account + * @throws AccountDoesNotExistException if the specified account does not exist + * @throws TransactionDoesNotExistException if the transaction cannot be found + */ + @Override + public void removeTransaction(String account, Transaction transaction) throws AccountDoesNotExistException, TransactionDoesNotExistException, IOException { + // 1. check if Account exists + if (this.containsAccount(account)) { + // 2. check if Transaction exists + if (this.containsTransaction(account, transaction)) { + this.accountsToTransactions.get(account).remove(transaction); + // 3. rewrite account because of change + writeAccount(account); + } + else + throw new TransactionDoesNotExistException(); + + } else { + throw new AccountDoesNotExistException(); + } + } + + /** + * Checks whether the specified transaction for a given account exists. + * + * @param account the account from which the transaction is checked + * @param transaction the transaction to search/look for + */ + @Override + public boolean containsTransaction(String account, Transaction transaction) { + return this.accountsToTransactions.containsKey(account) && + this.accountsToTransactions.get(account).contains(transaction); + } + + /** + * Checks whether the specified account exists. + * + * @param account account name + * @return exitens + */ + public boolean containsAccount(String account) { + return this.accountsToTransactions.containsKey(account); + } + + /** + * Calculates and returns the current account balance. + * + * @param account the selected account + * @return the current account balance + */ + @Override + public double getAccountBalance(String account) { + double balance = 0; + List transactions = accountsToTransactions.get(account); + + for (Transaction transaction : transactions) { + /* + * basierend auf den Transaktions Typen, wird die entsprechende calculate() aufgerufen + */ + balance += transaction.calculate(); + } + + return balance; + } + + /** + * Returns a list of transactions for an account. + * + * @param account the selected account + * @return the list of all transactions for the specified account + */ + @Override + public List getTransactions(String account) { + if (this.accountsToTransactions.containsKey(account)) + return this.accountsToTransactions.get(account); + else + return new ArrayList<>(); + } + + /** + * Returns a sorted list (-> calculated amounts) of transactions for a specific account. Sorts the list either in ascending or descending order + * (or empty). + * + * @param account the selected account + * @param asc selects if the transaction list is sorted in ascending or descending order + * @return the sorted list of all transactions for the specified account + */ + @Override + public List getTransactionsSorted(String account, boolean asc) { + List transactions = this.accountsToTransactions.get(account); + transactions.sort(Comparator.comparingDouble(Transaction::calculate)); + return transactions; + } + + /** + * Returns a list of either positive or negative transactions (-> calculated amounts). + * + * @param account the selected account + * @param positive selects if positive or negative transactions are listed + * @return the list of all transactions by type + */ + @Override + public List getTransactionsByType(String account, boolean positive) { + List transactions = this.accountsToTransactions.get(account); + if (positive) + transactions.removeIf(transaction -> transaction.calculate() >= 0); + else + transactions.removeIf(transaction -> transaction.calculate() < 0); + return transactions; + } + + /** + * Import Accounts from existing JSON Files + * @throws IOException if an error occurs while deserializing + */ + public void readAccounts() throws IOException, java.io.IOException { + /* + 1. JSONs einlesen + 2. for each Transaction + 1. basierend auf dem Kontotyp ein Objekt erzeugen + 2. Objekte in einer Liste zusammenführen + 3. Konto mit einer Liste von Transaktionen erzeugen + */ + + List transactionList; + File directory = new File(directoryName); + File[] files = {}; + int fileCount = 0; + + if (directory.exists() && directory.isDirectory()) { + files = directory.listFiles(); + if (files != null) + // Zähle nur die Dateien, nicht die Unterverzeichnisse + for (File file : files) if (file.isFile()) fileCount++; + } + + if(files.length > 0){ + // jedes file ist ein Konto + for (File file : files) { + String jsonContent = Files.readString(Paths.get(directoryName + "/" + file.getName())); + JsonElement accountData = JsonParser.parseString(jsonContent); + + for(JsonElement account: accountData.getAsJsonArray()) { + JsonObject accountObject = account.getAsJsonObject(); + + String transactionType = accountObject.get("CLASSNAME").getAsString(); + JsonElement transactionInstance = accountObject.get("INSTANCE").getAsJsonObject(); + + // Fallunterscheidung je nach Typ + deserialize() + } + } + } + } + + /** + * Export Account to JSON + * @param account Account to be exportet + * @throws IOException if an error occurs while serializing + */ + public void writeAccount(String account) throws IOException{ + /* + 1. alle Transactionen des Kontos abholen + 2. basierend auf Transactionstyp serialisieren + 3. zusammenpacken und speichern + */ + } + + + /** + * @param jsonElement + * @param type + * @param jsonDeserializationContext + * @return + * @throws JsonParseException + */ + @Override + public Transaction deserialize(JsonElement jsonElement, Type type, JsonDeserializationContext jsonDeserializationContext) throws JsonParseException { + return null; + } + + /** + * @param transaction + * @param type + * @param jsonSerializationContext + * @return + */ + @Override + public JsonElement serialize(Transaction transaction, Type type, JsonSerializationContext jsonSerializationContext) { + return null; + } +} diff --git a/src/main/java/bank/PrivateBankAlt.java b/src/main/java/bank/PrivateBankAlt.java new file mode 100644 index 0000000..647d6b0 --- /dev/null +++ b/src/main/java/bank/PrivateBankAlt.java @@ -0,0 +1,332 @@ +package bank; + +import bank.exceptions.*; + +import java.util.*; + +public class PrivateBankAlt implements Bank { + private String name; + private double incomingInterest; + private double outgoingInterest; + protected Map> accountsToTransactions = new HashMap<>(); + + /** + * @return Name of the Bank + */ + public String getName() { + return name; + } + + /** + * Sets the Name of the Bank + * + * @param newName Name + */ + public void setName(String newName) { + this.name = newName; + } + + /** + * @return IncomingInterest + */ + public double getIncomingInterest() { + return incomingInterest; + } + + /** + * Sets the IncomingInterest + * + * @param newIncomingInterest IncomingInterest + */ + public void setIncomingInterest(double newIncomingInterest) { + this.incomingInterest = newIncomingInterest; + } + + /** + * @return OutgoingInterest + */ + public double getOutgoingInterest() { + return outgoingInterest; + } + + /** + * Sets OutgoingInterest + * + * @param newOutgoingInterest OutgoingInterest + */ + public void setOutgoingInterest(double newOutgoingInterest) { + this.outgoingInterest = newOutgoingInterest; + } + + /** + * Default Constructor + * + * @param name Name + * @param incomingInterest incoming Interest + * @param outgoingInterest outgoing Interest + */ + public PrivateBankAlt(String name, double incomingInterest, double outgoingInterest) { + this.setName(name); + this.setIncomingInterest(incomingInterest); + this.setOutgoingInterest(outgoingInterest); + } + + /** + * Copy Constructor + * + * @param privateBank Bank to copy from + */ + public PrivateBankAlt(PrivateBank privateBank) { + this.setName(privateBank.getName()); + this.setIncomingInterest(privateBank.getIncomingInterest()); + this.setOutgoingInterest(privateBank.getOutgoingInterest()); + this.accountsToTransactions = privateBank.accountsToTransactions; + } + + @Override + public String toString() { + return ("\n--------------Bank-------------" + + "\n Name: " + this.getName() + + "\nIncomingInt: " + this.getIncomingInterest() + + "\nOutgoingInt: " + this.getOutgoingInterest() + + "\n-------------------------------\n" + ); + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof PrivateBank) { + PrivateBank privateBank = (PrivateBank) obj; + return this.getName().equals(privateBank.getName()) && + this.getIncomingInterest() == privateBank.getIncomingInterest() && + this.getOutgoingInterest() == privateBank.getOutgoingInterest() && + // Compares the values in the maps and not if the objects are the same + this.accountsToTransactions.equals(privateBank.accountsToTransactions); + } + return false; + } + + /** + * Adds an account to the bank. + * + * @param account the account to be added + * @throws AccountAlreadyExistsException if the account already exists + */ + @Override + public void createAccount(String account) throws AccountAlreadyExistsException { + if (this.accountsToTransactions.containsKey(account)) { + throw new AccountAlreadyExistsException(); + } else { + List transactions = new ArrayList<>(); + this.accountsToTransactions.put(account, transactions); + } + + } + + /** + * Adds an account (with specified transactions) to the bank. + * Important: duplicate transactions must not be added to the account! + * + * @param account the account to be added + * @param transactions a list of already existing transactions which should be added to the newly created account + * @throws AccountAlreadyExistsException if the account already exists + * @throws TransactionAlreadyExistException if the transaction already exists + * @throws TransactionAttributeException if the validation check for certain attributes fail + */ + + @Override + public void createAccount(String account, List transactions) throws AccountAlreadyExistsException, TransactionAlreadyExistException, TransactionAttributeException { + createAccount(account); + for (Transaction transaction : transactions) { + if (this.accountsToTransactions.get(account).contains(transaction)) + throw new TransactionAlreadyExistException(); + else if (checkTransactionAttributes(account, transaction)) + this.accountsToTransactions.get(account).add(transaction); + } + } + + /** + * Adds a transaction to an already existing account. + * + * @param account the account to which the transaction is added + * @param transaction the transaction which should be added to the specified account + * @throws TransactionAlreadyExistException if the transaction already exists + * @throws AccountDoesNotExistException if the specified account does not exist + * @throws TransactionAttributeException if the validation check for certain attributes fail + */ + @Override + public void addTransaction(String account, Transaction transaction) throws TransactionAlreadyExistException, AccountDoesNotExistException, TransactionAttributeException { + // 1. check if Account exists + if (this.containsAccount(account)) { + // 2. check if Transaction exists + if (this.containsTransaction(account, transaction)) + throw new TransactionAlreadyExistException(); + else if (checkTransactionAttributes(account, transaction)) + this.accountsToTransactions.get(account).add(transaction); + + } else { + throw new AccountDoesNotExistException(); + } + } + + /** + * Checking transaction to be added, if they contain all necessary and correct Attributes + * + * @param account account holder name + * @param transaction transaction + * @throws TransactionAttributeException if the validation check for certain attributes fail + */ + private boolean checkTransactionAttributes(String account, Transaction transaction) throws TransactionAttributeException { + // 1 Overwriting interest values if it is a payment + if (transaction instanceof Payment) { + ((Payment) transaction).setIncomingInterest(this.getIncomingInterest()); + ((Payment) transaction).setOutgoingInterest(this.getOutgoingInterest()); + return true; + } + + // 2 setting as incoming transfer + else if (transaction instanceof IncomingTransfer) { + if (((IncomingTransfer) transaction).getSender().equals("") || ((IncomingTransfer) transaction).getRecipient().equals("")) + throw new TransactionAttributeException("Transfer without sender or recipient"); + + else if (((IncomingTransfer) transaction).getRecipient().equals(account)) + return true; + else + throw new TransactionAttributeException("Transfer recipient is not account holder"); + } + + // 3 setting as outgoing transfer + else if (transaction instanceof OutgoingTransfer) { + if (((OutgoingTransfer) transaction).getSender().equals("") || ((OutgoingTransfer) transaction).getRecipient().equals("")) + throw new TransactionAttributeException("Transfer without sender or recipient"); + + else if (((OutgoingTransfer) transaction).getSender().equals(account)) + return true; + else + throw new TransactionAttributeException("Transfer sender is not account holder "); + } + return false; + } + + /** + * Removes a transaction from an account. If the transaction does not exist, an exception is + * thrown. + * + * @param account the account from which the transaction is removed + * @param transaction the transaction which is removed from the specified account + * @throws AccountDoesNotExistException if the specified account does not exist + * @throws TransactionDoesNotExistException if the transaction cannot be found + */ + @Override + public void removeTransaction(String account, Transaction transaction) throws AccountDoesNotExistException, TransactionDoesNotExistException { + // 1. check if Account exists + if (this.containsAccount(account)) { + // 2. check if Transaction exists + if (this.containsTransaction(account, transaction)) + this.accountsToTransactions.get(account).remove(transaction); + else + throw new TransactionDoesNotExistException(); + + } else { + throw new AccountDoesNotExistException(); + } + } + + /** + * Checks whether the specified transaction for a given account exists. + * + * @param account the account from which the transaction is checked + * @param transaction the transaction to search/look for + */ + @Override + public boolean containsTransaction(String account, Transaction transaction) { + return this.accountsToTransactions.containsKey(account) && + this.accountsToTransactions.get(account).contains(transaction); + } + + /** + * Checks whether the specified account exists. + * + * @param account account name + * @return exitens + */ + public boolean containsAccount(String account) { + return this.accountsToTransactions.containsKey(account); + } + + /** + * Calculates and returns the current account balance. + * + * @param account the selected account + * @return the current account balance + */ + @Override + public double getAccountBalance(String account) { + double balance = 0; + List transactions = accountsToTransactions.get(account); + + if (!transactions.isEmpty()) { + for (Transaction transaction : transactions) { + // adding or subtracting the amount based on type + + if (transaction instanceof IncomingTransfer) { + balance += transaction.getAmount(); + } else if (transaction instanceof OutgoingTransfer) { + balance -= transaction.getAmount(); + } else if (transaction instanceof Payment) { + balance += transaction.calculate(); + } + } + } + + return balance; + } + + + + /** + * Returns a list of transactions for an account. + * + * @param account the selected account + * @return the list of all transactions for the specified account + */ + @Override + public List getTransactions(String account) { + if (this.accountsToTransactions.containsKey(account)) + return this.accountsToTransactions.get(account); + else + return new ArrayList<>(); + } + + /** + * Returns a sorted list (-> calculated amounts) of transactions for a specific account. Sorts the list either in ascending or descending order + * (or empty). + * + * @param account the selected account + * @param asc selects if the transaction list is sorted in ascending or descending order + * @return the sorted list of all transactions for the specified account + */ + @Override + public List getTransactionsSorted(String account, boolean asc) { + List transactions = this.accountsToTransactions.get(account); + transactions.sort(Comparator.comparingDouble(Transaction::calculate)); + return transactions; + } + + /** + * Returns a list of either positive or negative transactions (-> calculated amounts). + * + * @param account the selected account + * @param positive selects if positive or negative transactions are listed + * @return the list of all transactions by type + */ + @Override + public List getTransactionsByType(String account, boolean positive) { + List transactions = this.accountsToTransactions.get(account); + if (positive) + transactions.removeIf(transaction -> transaction.calculate() >= 0); + else + transactions.removeIf(transaction -> transaction.calculate() < 0); + return transactions; + } +} diff --git a/src/main/java/bank/Transaction.java b/src/main/java/bank/Transaction.java new file mode 100644 index 0000000..f46a3c1 --- /dev/null +++ b/src/main/java/bank/Transaction.java @@ -0,0 +1,114 @@ +package bank; + +import bank.exceptions.TransactionAttributeException; +import com.google.gson.*; + +public abstract class Transaction implements CalculateBill{ + /** + * protected vars, which must be available throughout the whole package + */ + protected String date; + protected double amount; + protected String description; + + /** + * Sets the amount of the payment. + * + * @param newAmount The new amount for the payment. + */ + public void setAmount(double newAmount) throws TransactionAttributeException { + this.amount = newAmount; + } + + /** + * Gets the amount of the payment. + * + * @return The amount of the payment. + */ + public double getAmount() { + return amount; + } + + /** + * Sets the description of the payment. + * + * @param newDescription The new description for the payment. + */ + public void setDescription(String newDescription) { + this.description = newDescription; + } + + /** + * Gets the description of the payment. + * + * @return The description of the payment. + */ + public String getDescription() { + return description; + } + + /** + * Sets the date of the payment. + * + * @param newDate The new date for the payment. + */ + public void setDate(String newDate) { + this.date = newDate; + } + + /** + * Gets the date of the payment. + * + * @return The date of the payment. + */ + public String getDate() { + return date; + } + + /** + * Constructor for creating a transaction with date, amount, and description + * + * @param newDate The date of the transfer. + * @param newAmount The amount of the transfer. + * @param newDescription The description of the transfer. + */ + public Transaction(String newDate, double newAmount, String newDescription) throws TransactionAttributeException { + this.setAmount(newAmount); + this.setDescription(newDescription); + this.setDate(newDate); + } + + /** + * Prints the transaction details to the console. + * Amount is printed in the extended class, because of + * different conditions to be checked + */ + @Override + public String toString() { + return ("\n Date: " + this.getDate() + + "\nDescription: " + this.getDescription() + + "\n Amount: " + this.calculate() + ); + } + + /** + * Compares obj with current transaction + * + * @param obj The object to compare with + * @return Result of the comparison + */ + @Override + public boolean equals(Object obj) { + if (obj instanceof Transaction) { + Transaction other = (Transaction) obj; + return ( + this.getDate().equals(other.getDate()) && + this.getAmount() == other.getAmount() && + this.getDescription().equals(other.getDescription()) + ); + } + return false; + } + + +} diff --git a/src/main/java/bank/Transfer.java b/src/main/java/bank/Transfer.java new file mode 100644 index 0000000..901951e --- /dev/null +++ b/src/main/java/bank/Transfer.java @@ -0,0 +1,144 @@ +package bank; + +import bank.exceptions.TransactionAttributeException; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonElement; +import com.google.gson.JsonParseException; +import com.google.gson.JsonSerializationContext; + +import java.lang.reflect.Type; + +/** + * The Transfer class represents a financial transfer between two parties, + * including the date, amount, description, sender, and recipient. + */ +public class Transfer extends Transaction { + /** + * private variables + * initialized as empty Strings to avoid null-errors + */ + private String sender = ""; + private String recipient = ""; + + /** + * Sets the amount by checking if condition is valid + * @param newAmount The new amount for the payment. + */ + @Override + public void setAmount(double newAmount) throws TransactionAttributeException{ + if(newAmount >= 0) + this.amount = newAmount; + else + throw new TransactionAttributeException("Amount cannot be negative"); + } + + /** + * Sets the sender of the transfer. + * + * @param newSender The new sender for the transfer. + */ + public void setSender(String newSender) { + this.sender = newSender; + } + + /** + * Gets the sender of the transfer. + * + * @return The sender of the transfer. + */ + public String getSender() { + return sender; + } + + /** + * Sets the recipient of the transfer. + * + * @param newRecipient The new recipient for the transfer. + */ + public void setRecipient(String newRecipient) { + this.recipient = newRecipient; + } + + /** + * Gets the recipient of the transfer. + * + * @return The recipient of the transfer. + */ + public String getRecipient() { + return recipient; + } + + /** + * Constructor for creating a transfer with date, amount, and description + * based on abstract class + * + * @param newDate The date of the transfer. + * @param newAmount The amount of the transfer. + * @param newDescription The description of the transfer. + */ + public Transfer(String newDate, double newAmount, String newDescription) throws TransactionAttributeException { + super(newDate, newAmount, newDescription); + } + + @Override + public double calculate() { + return this.getAmount(); + } + + /** + * Constructor for creating a transfer with date, amount, description, + * sender, and recipient based on abstract class + * + * @param newDate The date of the transfer. + * @param newAmount The amount of the transfer. + * @param newDescription The description of the transfer. + * @param newSender The sender of the transfer. + * @param newRecipient The recipient of the transfer. + */ + public Transfer(String newDate, double newAmount, String newDescription, String newSender, String newRecipient) throws TransactionAttributeException { + super(newDate, newAmount, newDescription); + this.setSender(newSender); + this.setRecipient(newRecipient); + } + + /** + * Copy constructor to create a new Transfer object based on an existing one. + * + * @param t The Transfer object to copy from. + */ + public Transfer(Transfer t) throws TransactionAttributeException { + this(t.getDate(), t.getAmount(), t.getDescription(), t.getSender(), t.getRecipient()); + } + + /** + * Prints the transfer details to the console. + */ + @Override + public String toString() { + return ("\n------------Transfer-----------" + + super.toString()+ + "\n Sender: " + this.getSender() + + "\n Recipient: " + this.getRecipient() + + "\n-------------------------------\n" + ); + } + + /** + * Compares obj with current transaction + * + * @param obj The object to compare with + * @return Result of the comparison + */ + @Override + public boolean equals(Object obj) { + if (obj instanceof Transfer) { + Transfer t = (Transfer) obj; + return( + super.equals(t) && + this.getSender().equals(t.getSender()) && + this.getRecipient().equals(t.getRecipient()) + ); + } + return false; + } +} diff --git a/src/main/java/bank/exceptions/AccountAlreadyExistsException.java b/src/main/java/bank/exceptions/AccountAlreadyExistsException.java new file mode 100644 index 0000000..874c0b8 --- /dev/null +++ b/src/main/java/bank/exceptions/AccountAlreadyExistsException.java @@ -0,0 +1,7 @@ +package bank.exceptions; + +public class AccountAlreadyExistsException extends Exception { + public AccountAlreadyExistsException() { + super("Account already exists"); + } +} diff --git a/src/main/java/bank/exceptions/AccountDoesNotExistException.java b/src/main/java/bank/exceptions/AccountDoesNotExistException.java new file mode 100644 index 0000000..449258c --- /dev/null +++ b/src/main/java/bank/exceptions/AccountDoesNotExistException.java @@ -0,0 +1,7 @@ +package bank.exceptions; + +public class AccountDoesNotExistException extends Exception { + public AccountDoesNotExistException(){ + super("Account does not exist"); + } +} diff --git a/src/main/java/bank/exceptions/IOException.java b/src/main/java/bank/exceptions/IOException.java new file mode 100644 index 0000000..f3ec705 --- /dev/null +++ b/src/main/java/bank/exceptions/IOException.java @@ -0,0 +1,7 @@ +package bank.exceptions; + +public class IOException extends Exception { + public IOException() { + super("Fehler in der De-/ Serialisierung der Daten"); + } +} diff --git a/src/main/java/bank/exceptions/TransactionAlreadyExistException.java b/src/main/java/bank/exceptions/TransactionAlreadyExistException.java new file mode 100644 index 0000000..f4e6686 --- /dev/null +++ b/src/main/java/bank/exceptions/TransactionAlreadyExistException.java @@ -0,0 +1,7 @@ +package bank.exceptions; + +public class TransactionAlreadyExistException extends Exception { + public TransactionAlreadyExistException() { + super("Transaction already exists"); + } +} diff --git a/src/main/java/bank/exceptions/TransactionAttributeException.java b/src/main/java/bank/exceptions/TransactionAttributeException.java new file mode 100644 index 0000000..b37e3d8 --- /dev/null +++ b/src/main/java/bank/exceptions/TransactionAttributeException.java @@ -0,0 +1,7 @@ +package bank.exceptions; + +public class TransactionAttributeException extends Exception { + public TransactionAttributeException(String message) { + super(message); + } +} diff --git a/src/main/java/bank/exceptions/TransactionDoesNotExistException.java b/src/main/java/bank/exceptions/TransactionDoesNotExistException.java new file mode 100644 index 0000000..68e3099 --- /dev/null +++ b/src/main/java/bank/exceptions/TransactionDoesNotExistException.java @@ -0,0 +1,7 @@ +package bank.exceptions; + +public class TransactionDoesNotExistException extends Exception { + public TransactionDoesNotExistException() { + super("Transaction does not exist"); + } +}