diff --git a/.gitignore b/.gitignore index 29fcd18..b356010 100644 --- a/.gitignore +++ b/.gitignore @@ -14,4 +14,5 @@ project/plugins/project/ # IntelliJ .idea -*.iml \ No newline at end of file +*.iml +/bin diff --git a/build.sbt b/build.sbt index 005b43d..81657d9 100644 --- a/build.sbt +++ b/build.sbt @@ -4,4 +4,7 @@ version := "1.0" scalaVersion := "2.11.0" -libraryDependencies += "org.scalatest" % "scalatest_2.11" % "2.1.6" % "test" \ No newline at end of file +libraryDependencies += "org.scalatest" % "scalatest_2.11" % "2.1.6" % "test" +libraryDependencies ++= Seq( "joda-time" % "joda-time" % "2.3" + , "org.joda" % "joda-convert" % "1.6" + ) \ No newline at end of file diff --git a/src/main/scala/com/abc/Account.scala b/src/main/scala/com/abc/Account.scala index fa23d85..a88811e 100644 --- a/src/main/scala/com/abc/Account.scala +++ b/src/main/scala/com/abc/Account.scala @@ -1,6 +1,7 @@ package com.abc import scala.collection.mutable.ListBuffer +import org.joda.time.{DateTime, Days} object Account { final val CHECKING: Int = 0 @@ -31,14 +32,38 @@ class Account(val accountType: Int, var transactions: ListBuffer[Transaction] = if (amount <= 1000) amount * 0.001 else 1 + (amount - 1000) * 0.002 case Account.MAXI_SAVINGS => - if (amount <= 1000) return amount * 0.02 - if (amount <= 2000) return 20 + (amount - 1000) * 0.05 - 70 + (amount - 2000) * 0.1 + numOfDaysSinceLastWithdrawal match { + case Some(daysInterval) if daysInterval >= 10 => amount * 0.05 + case Some(daysInterval) => amount * 0.001 + case None if numOfDaysSinceFirstDeposit > 10 => amount * 0.05 + case _ => amount * 0.001 + } + //if (amount <= 1000) return amount * 0.02 + //if (amount <= 2000) return 20 + (amount - 1000) * 0.05 + //70 + (amount - 2000) * 0.1 case _ => amount * 0.001 } } def sumTransactions(checkAllTransactions: Boolean = true): Double = transactions.map(_.amount).sum + + private def numOfDaysSinceLastWithdrawal():Option[Int] = { + transactions.reverse find ( _.amount < 0) match { + case Some(lastWithdrawTrans) => { val lastWithdrawDateTime = new DateTime(lastWithdrawTrans.transactionDate); + val currDateTime = new DateTime(); + val daysInterval = Days.daysBetween(currDateTime , lastWithdrawDateTime).getDays(); + Some(daysInterval) + } + case None =>{ println("we are in None"); None } + } + } + + private def numOfDaysSinceFirstDeposit:Int = { + val firstdepositDateTime = new DateTime(transactions.head.transactionDate); + val currDateTime = new DateTime(); + val daysInterval = Days.daysBetween(currDateTime , firstdepositDateTime).getDays(); + daysInterval + } } \ No newline at end of file diff --git a/src/main/scala/com/abc/Customer.scala b/src/main/scala/com/abc/Customer.scala index 6c517b0..fe12aab 100644 --- a/src/main/scala/com/abc/Customer.scala +++ b/src/main/scala/com/abc/Customer.scala @@ -12,6 +12,9 @@ class Customer(val name: String, var accounts: ListBuffer[Account] = ListBuffer( def numberOfAccounts: Int = accounts.size def totalInterestEarned: Double = accounts.map(_.interestEarned).sum + private var fromAccount = None: Option[Account] + private var toAccount = None: Option[Account] + /** * This method gets a statement @@ -49,6 +52,41 @@ class Customer(val name: String, var accounts: ListBuffer[Account] = ListBuffer( case _ => "N/A" } - private def toDollars(number: Double): String = f"$$$number%.2f" + private def toDollars(number: Double): String = f"$$$number%.2f" + + // Adding method to find is account exist for Customer to and from transfer is happening + private def accountExist(account: Account): Boolean = { + accounts.contains(account) + } + + def transferFrom(account: Account): Customer={ + if (!accountExist(account)) + throw new IllegalArgumentException(f"No Such Account exist for $name\n") + else{ + fromAccount = Some(account) + this} + } + def transferTo(account: Account): Customer={ + if (!accountExist(account)) + throw new IllegalArgumentException(f"No Such Account exist for $name\n") + else{ + toAccount = Some(account) + this} + } + + def transferAmount(amount: Double) = { + try { + fromAccount match { + case Some(fAccount) if amount > 0 && (fAccount.sumTransactions(true) >= amount) => toAccount match { + case Some(tAccount) => { fAccount.withdraw(amount); tAccount.deposit(amount) } + case None => throw new IllegalArgumentException(f"Transaction failed \n") + } + case None => throw new IllegalArgumentException(f"Transaction failed \n") + } + } catch{ + case ex: Exception => printf(s"${ex.getMessage()} \n") + } + } + } diff --git a/src/test/scala/com/abc/BankTest.scala b/src/test/scala/com/abc/BankTest.scala index 13b3067..a920954 100644 --- a/src/test/scala/com/abc/BankTest.scala +++ b/src/test/scala/com/abc/BankTest.scala @@ -35,5 +35,15 @@ class BankTest extends FlatSpec with Matchers { checkingAccount.deposit(3000.0) bank.totalInterestPaid should be(170.0) } + + it should "maxi savings accounts rate as 5% assuming no withdrawals" in { + val bank: Bank = new Bank + val checkingAccount: Account = new Account(Account.MAXI_SAVINGS) + bank.addCustomer(new Customer("Bill").openAccount(checkingAccount)) + checkingAccount.deposit(300.000) + checkingAccount.withdraw(100.000) + checkingAccount.deposit(10.000) + bank.totalInterestPaid should be(0.210) + } } diff --git a/src/test/scala/com/abc/CustomerTest.scala b/src/test/scala/com/abc/CustomerTest.scala index 96652b4..49fd3b4 100644 --- a/src/test/scala/com/abc/CustomerTest.scala +++ b/src/test/scala/com/abc/CustomerTest.scala @@ -27,9 +27,23 @@ class CustomerTest extends FlatSpec with Matchers { oscar.numberOfAccounts should be(2) } + it should "testTransferBetweenTwoAccounts" in { + val checkingAccount: Account = new Account(Account.CHECKING) + val savingsAccount: Account = new Account(Account.SAVINGS) + val John: Customer = new Customer("Henry").openAccount(checkingAccount).openAccount(savingsAccount) + checkingAccount.deposit(200.0) + savingsAccount.deposit(400.0) + + John.transferFrom(checkingAccount).transferTo(savingsAccount).transferAmount(150.00) + checkingAccount.sumTransactions(true) should be(50.0) + savingsAccount.sumTransactions(true) should be(550.0) + } + ignore should "testThreeAcounts" in { val oscar: Customer = new Customer("Oscar").openAccount(new Account(Account.SAVINGS)) oscar.openAccount(new Account(Account.CHECKING)) oscar.numberOfAccounts should be(3) } + + }