diff --git a/.gitignore b/.gitignore index 95abee5..d20e704 100644 --- a/.gitignore +++ b/.gitignore @@ -103,4 +103,5 @@ target/* .project .classpath -.settings \ No newline at end of file +.settings +/target/ diff --git a/src/main/java/io/zipcoder/Account.java b/src/main/java/io/zipcoder/Account.java deleted file mode 100644 index 1a0742e..0000000 --- a/src/main/java/io/zipcoder/Account.java +++ /dev/null @@ -1,4 +0,0 @@ -package io.zipcoder; - -public abstract class Account { -} diff --git a/src/main/java/io/zipcoder/Transaction.java b/src/main/java/io/zipcoder/Transaction.java new file mode 100644 index 0000000..d81b73c --- /dev/null +++ b/src/main/java/io/zipcoder/Transaction.java @@ -0,0 +1,36 @@ +package io.zipcoder; + +//import java.util.Date; + +public class Transaction { + + //private Date timeStamp; + private final String type; + private final double transactionAmount; + private final double newBalance; + + public Transaction(String type, double transactionAmount, double newBalance){ + this.type = type; + this.transactionAmount = transactionAmount; + this.newBalance = newBalance; + //this.timeStamp = new Date(); + } + + /** + * @return the transactionAmount + */ + public double getTransactionAmount() { + return transactionAmount; + } + /** + * @return the remaining + */ + public double getRemaining() { + return newBalance; + } + + public String toString(){ + return String.format("transaction type %s. Transaction amount: £%.2f, new balance is: £%.2f",this.type, getTransactionAmount(), getRemaining()); + //return "transaction type " + this.type + ". Transaction amount: £" + this.transactionAmount + ", new balance is: £" + this.newBalance; + } +} diff --git a/src/main/java/io/zipcoder/accountHolders/AccountHolder.java b/src/main/java/io/zipcoder/accountHolders/AccountHolder.java new file mode 100644 index 0000000..609cef4 --- /dev/null +++ b/src/main/java/io/zipcoder/accountHolders/AccountHolder.java @@ -0,0 +1,6 @@ +package io.zipcoder.accountHolders; +public abstract class AccountHolder { + + public abstract String getName(); + +} \ No newline at end of file diff --git a/src/main/java/io/zipcoder/accountHolders/Business.java b/src/main/java/io/zipcoder/accountHolders/Business.java new file mode 100644 index 0000000..63d0174 --- /dev/null +++ b/src/main/java/io/zipcoder/accountHolders/Business.java @@ -0,0 +1,29 @@ +package io.zipcoder.accountHolders; + +public class Business extends AccountHolder{ + + private String businessName; + + public Business(String businessName) { + this.businessName = businessName; + } + + public String getName(){ + return this.getBusinessName(); + } + + /** + * @return the businessName + */ + public String getBusinessName() { + return businessName; + } + + /** + * @param businessName the businessName to set + */ + public void setBusinessName(String businessName) { + this.businessName = businessName; + } + +} diff --git a/src/main/java/io/zipcoder/accountHolders/Person.java b/src/main/java/io/zipcoder/accountHolders/Person.java new file mode 100644 index 0000000..892950f --- /dev/null +++ b/src/main/java/io/zipcoder/accountHolders/Person.java @@ -0,0 +1,60 @@ +package io.zipcoder.accountHolders; + +public class Person extends AccountHolder{ + + private String firstName; + private String middleInitials; + private String lastName; + + + //TODO: + // ??? toString - returns output of getName ??? + + public Person(String firstName, String middleInitials, String lastName){ + setFirstName(firstName); + setMiddleInitials(middleInitials); + setLastName(lastName); + } + + public String getName(){ + return getFirstName() + " " + getMiddleInitials() + " " + getLastName(); // format?? + } + + /** + * @return the firstName + */ + public String getFirstName() { + return firstName; + } + /** + * @param firstName the firstName to set + */ + public void setFirstName(String firstName) { + this.firstName = firstName; + } + /** + * @return the middleInitials + */ + public String getMiddleInitials() { + return middleInitials; + } + /** + * @param middleInitials the middleInitials to set + */ + public void setMiddleInitials(String middleInitials) { + this.middleInitials = middleInitials; + } + /** + * @return the lastName + */ + public String getLastName() { + return lastName; + } + /** + * @param lastName the lastName to set + */ + public void setLastName(String lastName) { + this.lastName = lastName; + } + +} diff --git a/src/main/java/io/zipcoder/accounts/Account.java b/src/main/java/io/zipcoder/accounts/Account.java new file mode 100644 index 0000000..a10aa18 --- /dev/null +++ b/src/main/java/io/zipcoder/accounts/Account.java @@ -0,0 +1,89 @@ +package io.zipcoder.accounts; + +import java.util.ArrayList; + +import io.zipcoder.Transaction; +import io.zipcoder.accountHolders.AccountHolder; + +public abstract class Account { + + private final AccountHolder accountHolder; + private double balance; + protected final long accountNumber; + private final ArrayList transactions; + + private static long accountNumberIncrementor = 0; + + protected Account(AccountHolder accountHolder) { + this.accountHolder = accountHolder; + this.balance = 0.00; + this.transactions = new ArrayList(); + this.accountNumber = generateAccountNumber(); + } + + protected void creditAccount(double amount) { + this.creditAccount("credit account", amount); + } + protected void creditAccount(String transactionType, double amount) { + if (amount >= 0) { + this.balance += amount; + // transaction + this.transactions.add(new Transaction(transactionType, amount, this.balance)); + } else { + throw new IllegalArgumentException("amount cannot be negative"); + } + } + + protected void debitAccount(double amount) { + if (amount >= 0) { + this.balance -= amount; + // transaction + this.transactions.add(new Transaction("debit account", amount, this.balance)); + } else { + throw new IllegalArgumentException("amount cannot be negative"); + } + } + + /** + * @return the accountHolder + */ + public AccountHolder getAccountHolder() { + return accountHolder; + } + + /** + * @return the balance + */ + public double getBalance() { + return balance; + } + + /** + * @return the accountNumber + */ + public long getAccountNumber() { + return accountNumber; + } + + /** + * @return the transactions + */ + public ArrayList getTransactions() { + return (ArrayList) this.transactions.clone(); + } + + public String getTransactionLog(int n) { + + StringBuilder returnBuilder = new StringBuilder("Transaction Log:"); + for (int i = transactions.size() -1; i >= transactions.size()-n; i--) { + returnBuilder.append("\n" + transactions.get(i).toString()); + } + return returnBuilder.toString(); + } + + private long generateAccountNumber() { + accountNumberIncrementor++; + return accountNumberIncrementor; + } + +} diff --git a/src/main/java/io/zipcoder/accounts/CheckingAccount.java b/src/main/java/io/zipcoder/accounts/CheckingAccount.java new file mode 100644 index 0000000..fefe5f2 --- /dev/null +++ b/src/main/java/io/zipcoder/accounts/CheckingAccount.java @@ -0,0 +1,60 @@ +package io.zipcoder.accounts; + +import io.zipcoder.accountHolders.AccountHolder; + +public class CheckingAccount extends Account { + + private boolean canHaveOverdraft = false; + private double overdraftLimit = 0.0; + + public CheckingAccount(AccountHolder accountHolder, + double overdraftLimit, boolean canHaveOverdraft) { + super(accountHolder); + this.setOverdraftLimit(overdraftLimit); + this.setCanHaveOverdraft(canHaveOverdraft); + } + + @Override + public void debitAccount(double amount) { + if (this.canHaveOverdraft() && this.getBalance() - amount >= -(this.getOverdraftLimit())) { + super.debitAccount(amount); + } else if (this.getBalance() - amount >= 0) { + super.debitAccount(amount); + } + } + + /** + * @return the canHaveOverdraft + */ + public boolean canHaveOverdraft() { + return canHaveOverdraft; + } + + /** + * @param canHaveOverdraft + * the canHaveOverdraft to set + */ + public void setCanHaveOverdraft(boolean canHaveOverdraft) { + this.canHaveOverdraft = canHaveOverdraft; + } + + /** + * @return the overdraftLimit + */ + public double getOverdraftLimit() { + return overdraftLimit; + } + + /** + * @param overdraftLimit + * the overdraftLimit to set + */ + public void setOverdraftLimit(double overdraftLimit) { + if (overdraftLimit >= 0) { + this.overdraftLimit = overdraftLimit; + } else { + this.overdraftLimit = 0; + } + } + +} diff --git a/src/main/java/io/zipcoder/accounts/InterestEnabledAccount.java b/src/main/java/io/zipcoder/accounts/InterestEnabledAccount.java new file mode 100644 index 0000000..7c22e0a --- /dev/null +++ b/src/main/java/io/zipcoder/accounts/InterestEnabledAccount.java @@ -0,0 +1,23 @@ +package io.zipcoder.accounts; + +public interface InterestEnabledAccount { + + /** + * @return the interest + */ + double getInterest(); + + /** + * @param intrest + * the interest to set, this should be relative to 1 (ie, setting + * interest to 1 is equivalent to 0% interest; 1.01 is equivalent to 1% interest) and cannot be + * negative. + */ + void setInterest(double interest); + + /** + * applies interest to the account, automatically debits and logs this as an interest transaction. + */ + void applyInterest(); + +} \ No newline at end of file diff --git a/src/main/java/io/zipcoder/accounts/InvestmentAccount.java b/src/main/java/io/zipcoder/accounts/InvestmentAccount.java new file mode 100644 index 0000000..d8e8044 --- /dev/null +++ b/src/main/java/io/zipcoder/accounts/InvestmentAccount.java @@ -0,0 +1,49 @@ +package io.zipcoder.accounts; + +import io.zipcoder.accountHolders.AccountHolder; + +public class InvestmentAccount extends Account implements InterestEnabledAccount { + + private double interest; + + /** + * + * @param accountHolder + * must be an accountHolder + * @param interest + * a value relative to 1 and greater than 0, where 1 is 0% + * interest. + */ + protected InvestmentAccount(AccountHolder accountHolder, double interest) { + super(accountHolder); + this.setInterest(interest); + } + + /** + * applies interest to the account, automatically debits and logs this as an + * interest transaction. + */ + public void applyInterest() { + // balance *= this.interest + this.creditAccount("interest", (this.getBalance() * this.interest - this.getBalance())); + } + + public double getInterest() { + return this.interest; + } + + /** + * @param intrest + * the interest to set, this should be relative to 1 (ie, setting + * interest to 1 is equivalent to 0% interest; 1.01 is equivalent + * to 1% interest) and cannot be negative. + */ + public void setInterest(double interest) { + if (interest >= 0) { + this.interest = interest; + } else { + throw new IllegalArgumentException("interest rate must be relative to 1, and greater than 0."); + } + } + +} diff --git a/src/main/java/io/zipcoder/accounts/SavingsAccount.java b/src/main/java/io/zipcoder/accounts/SavingsAccount.java new file mode 100644 index 0000000..b3e0286 --- /dev/null +++ b/src/main/java/io/zipcoder/accounts/SavingsAccount.java @@ -0,0 +1,25 @@ +package io.zipcoder.accounts; + +import io.zipcoder.accountHolders.AccountHolder; + +public class SavingsAccount extends CheckingAccount implements InterestEnabledAccount { + + private double interest; + + public SavingsAccount(AccountHolder accountHolder, double overdraftLimit, boolean canHaveOverdraft) { + super(accountHolder, overdraftLimit, canHaveOverdraft); + } + + public double getInterest() { + return this.interest; + } + + public void setInterest(double interest) { + this.interest = interest; + } + + public void applyInterest() { + this.creditAccount("interest", (this.getBalance() * this.interest - this.getBalance())); + } + +} diff --git a/src/test/java/io/zipcoder/AccountTest.java b/src/test/java/io/zipcoder/AccountTest.java deleted file mode 100644 index f4e8dee..0000000 --- a/src/test/java/io/zipcoder/AccountTest.java +++ /dev/null @@ -1,4 +0,0 @@ -package io.zipcoder; - -public class AccountTest { -} diff --git a/src/test/java/io/zipcoder/TransactionTest.java b/src/test/java/io/zipcoder/TransactionTest.java new file mode 100644 index 0000000..fefe6d9 --- /dev/null +++ b/src/test/java/io/zipcoder/TransactionTest.java @@ -0,0 +1,25 @@ +package io.zipcoder; + +import org.junit.Test; +import org.junit.Assert; + +public class TransactionTest { + + @Test + public void createTransactionAndPrintToStringTest() { + + // Given + Transaction t = new Transaction("intrest accured", 1.5, 101.5); + String expected = "transaction type intrest accured. " + + "Transaction amount: £1.50, new balance is: £101.50"; + + // When + String actual = t.toString(); + + // Then + Assert.assertEquals("create a transaction and test the toString method, " + + "no error was thrown and string was as expected", + expected, actual); + } + +} diff --git a/src/test/java/io/zipcoder/accountHolders/PersonTest.java b/src/test/java/io/zipcoder/accountHolders/PersonTest.java new file mode 100644 index 0000000..7816391 --- /dev/null +++ b/src/test/java/io/zipcoder/accountHolders/PersonTest.java @@ -0,0 +1,32 @@ +package io.zipcoder.accountHolders; + +import org.junit.Assert; +import org.junit.Test; + +import io.zipcoder.accountHolders.Person; + +public class PersonTest { + + @Test + public void testGetName() { + + boolean couldCreateAccount = true; + + try{ + // Given + Person p = new Person ("Alfred","H.G.","Wells"); + String expected = "Alfred H.G. Wells"; + + // When + String actual = p.getName(); + + // Then + Assert.assertEquals("testGetName() - strings were equal",expected, actual); + + } catch (Exception e) { + couldCreateAccount = false; + } + Assert.assertTrue("testGetName() - failed to create a person",couldCreateAccount); + } + +} diff --git a/src/test/java/io/zipcoder/accounts/AccountTest.java b/src/test/java/io/zipcoder/accounts/AccountTest.java new file mode 100644 index 0000000..30823c2 --- /dev/null +++ b/src/test/java/io/zipcoder/accounts/AccountTest.java @@ -0,0 +1,3 @@ +package io.zipcoder.accounts; + +public class AccountTest {} \ No newline at end of file diff --git a/src/test/java/io/zipcoder/accounts/CheckingAccountTest.java b/src/test/java/io/zipcoder/accounts/CheckingAccountTest.java new file mode 100644 index 0000000..1506ee3 --- /dev/null +++ b/src/test/java/io/zipcoder/accounts/CheckingAccountTest.java @@ -0,0 +1,89 @@ +package io.zipcoder.accounts; + +import org.junit.Test; + +import io.zipcoder.accountHolders.AccountHolder; +import io.zipcoder.accountHolders.Person; +import io.zipcoder.accounts.CheckingAccount; + +import org.junit.Assert; + +public class CheckingAccountTest { + + @Test + public void setOverdraftLimitTest() { + + // Given (1) + AccountHolder zac = new Person("Zac", "J", "Effron"); + CheckingAccount checkingAccount = new CheckingAccount(zac, 0, true); + double expectedT1 = 100.0; + + // When (1) + checkingAccount.setOverdraftLimit(100); + double actualT1 = checkingAccount.getOverdraftLimit(); + + // Then (1) + Assert.assertEquals("setOverdraftLimitTest - limit >= 0 - expected number matched actual", expectedT1, actualT1, + 0); + + // Given (2) + double expectedT2 = 0; + + // When (2) + checkingAccount.setOverdraftLimit(-100); + double actualT2 = 0; + + // Then (2) + Assert.assertEquals("setOverdraftLimitTest - limit < 0 - expected number matched actual", expectedT2, actualT2, + 0); + + } + + @Test + public void debitAccountTest(){ + + //Given (1,2,3) + AccountHolder zac = new Person("Zac", "J", "Effron"); + CheckingAccount checkingAccount = new CheckingAccount(zac, 0, true); + checkingAccount.creditAccount(100); + + // ------ Test 1, debit account outside of overdraft, normally + + // Given (1) + double expected = 50.0; + + // When (1) + checkingAccount.debitAccount(50); + double actual = checkingAccount.getBalance(); + + // Then (1) + Assert.assertEquals("debitAccounTest() - regular debit test", expected, actual,0); + + // ------ Test 2, debit account more than the overdraft limit + + // Given (2) + checkingAccount.setCanHaveOverdraft(true); + checkingAccount.setOverdraftLimit(100); + double expected2 = -50; + + // When (2) + checkingAccount.debitAccount(100); + double actual2 = checkingAccount.getBalance(); + + // Then (3) + Assert.assertEquals("debitAccounTest() - debit into allowed overdraft range", expected2, actual2,0); + + // ------ Test 3, debit account within the overdraft limit and see if everything works. + + // Given (3) + checkingAccount.debitAccount(100); // should not be allowed, and balance would be equal + double expected3 = -50; + + //When (3) + double actual3 = checkingAccount.getBalance(); + + // Test (3) + Assert.assertEquals("debitAccounTest() - debit into unallowed overdraft range", expected3, actual3,0); + } + +} diff --git a/src/test/java/io/zipcoder/accounts/InvestmentAccountTest.java b/src/test/java/io/zipcoder/accounts/InvestmentAccountTest.java new file mode 100644 index 0000000..6fb916b --- /dev/null +++ b/src/test/java/io/zipcoder/accounts/InvestmentAccountTest.java @@ -0,0 +1,156 @@ +package io.zipcoder.accounts; + +import org.junit.Test; + +import io.zipcoder.accountHolders.AccountHolder; +import io.zipcoder.accountHolders.Business; +import io.zipcoder.accountHolders.Person; +import io.zipcoder.accounts.InterestEnabledAccount; +import io.zipcoder.accounts.InvestmentAccount; + +import org.junit.Assert; + +public class InvestmentAccountTest { + // This class also tests functionality written in the Accounts class + + @Test + public void createInvestmentAccountTest() { + + // Given & When + try { + AccountHolder zac = new Person("Zac", "J", "Effron"); + InterestEnabledAccount investmentAccount = new InvestmentAccount(zac, 1.01); + } catch (Exception e) { + // if an error occurs the methods failed. + Assert.fail(); + } // else everything worked + + } + + @Test + public void creditInvestmentAccountTest() { + + // Given + AccountHolder zac = new Person("Zac", "J", "Effron"); + InvestmentAccount investmentAccount = new InvestmentAccount(zac, 1.01); + double amount = 100; + + // When + investmentAccount.creditAccount(amount); + + // Then + Assert.assertEquals("credit Investment Account Test - doubles were equal", amount, + investmentAccount.getBalance(), 0.0); + + // Given When & Then (2) + try { + investmentAccount.creditAccount(-50); + Assert.assertTrue( + "creditIvenstmentAccountTest - credit account with negative number - illegalArgumentException was raised", + false); + } catch (IllegalArgumentException e) { + Assert.assertTrue( + "creditIvenstmentAccountTest - credit account with negative number - illegalArgumentException was raised", + true); + } + } + + @Test + public void debitInvestentAccountTest() { + + // Given + AccountHolder zac = new Business("Z. Effron Films Inc."); + InvestmentAccount investmentAccount = new InvestmentAccount(zac, 1.01); + investmentAccount.creditAccount(100.0); + double expected = 50.0; + + // When + investmentAccount.debitAccount(50.0); + double actual = investmentAccount.getBalance(); + + // Then + Assert.assertEquals("debit Investment Account Test - doubles were equal", expected, actual, 0.0); + + // Given When & Then (2) + try { + investmentAccount.debitAccount(-50); + Assert.assertTrue( + "debitIvenstmentAccountTest - debit account with negative number - illegalArgumentException was raised", + false); + } catch (IllegalArgumentException e) { + Assert.assertTrue( + "debitIvenstmentAccountTest - debit account with negative number - illegalArgumentException was raised", + true); + } + } + + @Test + public void setInterestTest() { + + // :Given (1) - positive interest rate test + AccountHolder zac = new Person("Zac", "J", "Effron"); + InvestmentAccount investmentAccount = new InvestmentAccount(zac, 1); + investmentAccount.setInterest(1.01); + double expected = 1.01; + + // :When (1) + double actual = investmentAccount.getInterest(); + + // :Then (1) + Assert.assertEquals("setInterestTest - positive interest test passed", expected, actual, 0); + + // :Given When & Then (2) - negative interest rate test + try{ + investmentAccount.setInterest(-0.1); + Assert.assertTrue("setInterestTest - set negative interest rate - illegalArgumentException was raised", + false); + } catch (IllegalArgumentException e) { + Assert.assertTrue("setInterestTest - set negative interest rate - illegalArgumentException was raised", + true); + } + + } + + @Test + public void applyInterstTest() { + + // Given + AccountHolder zac = new Person("Zac", "J", "Effron"); + InvestmentAccount investmentAccount = new InvestmentAccount(zac, 1.01); + investmentAccount.creditAccount(100.0); + double expected = 100 * 1.01; + + // When + investmentAccount.applyInterest(); + double actual = investmentAccount.getBalance(); + + // Then + Assert.assertEquals("debit Investment Account Test - doubles were equal", expected, actual, 0.0); + } + + @Test + public void getTransactionLogTest() { + + // Given + AccountHolder zac = new Person("Zac", "J", "Effron"); + InvestmentAccount investmentAccount = new InvestmentAccount(zac, 1.01); + investmentAccount.creditAccount(100.0); + investmentAccount.debitAccount(30.0); + investmentAccount.creditAccount(10.0); + investmentAccount.applyInterest(); + + String expected = "Transaction Log:" + + "\ntransaction type interest. Transaction amount: £0.80, new balance is: £80.80" + + "\ntransaction type credit account. Transaction amount: £10.00, new balance is: £80.00" + + "\ntransaction type debit account. Transaction amount: £30.00, new balance is: £70.00" + + "\ntransaction type credit account. Transaction amount: £100.00, new balance is: £100.00"; + + // When + String actual = investmentAccount.getTransactionLog(4); + + // Then + Assert.assertEquals("getTransactionLogTest - strings were equal", expected, actual); + + } + +} diff --git a/src/test/java/io/zipcoder/accounts/SavingsAccountTest.java b/src/test/java/io/zipcoder/accounts/SavingsAccountTest.java new file mode 100644 index 0000000..54aba76 --- /dev/null +++ b/src/test/java/io/zipcoder/accounts/SavingsAccountTest.java @@ -0,0 +1,30 @@ +package io.zipcoder.accounts; + +import org.junit.Assert; +import org.junit.Test; + +import io.zipcoder.accountHolders.Business; + +public class SavingsAccountTest { + + @Test + public void testApplyInterest() { + + // :Given + Business b = new Business("Jerome Savings Inc."); + SavingsAccount s = new SavingsAccount(b, 0, true); + s.setInterest(1.01); + s.setOverdraftLimit(1000); + s.debitAccount(100); + s.creditAccount(200); + double expected = (0-100+200)*1.01; + + // :When + s.applyInterest(); + double actual = s.getBalance(); + + // :Then + Assert.assertEquals("testApplyInterest - doubles matched", expected, actual, 0.001); + } + +}