Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

changes from vsftam #12

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 52 additions & 22 deletions src/main/scala/com/abc/Account.scala
Original file line number Diff line number Diff line change
@@ -1,44 +1,74 @@
package com.abc

import scala.collection.mutable.ListBuffer
import java.util.Calendar
import java.util.Date

object Account {
final val CHECKING: Int = 0
final val SAVINGS: Int = 1
final val MAXI_SAVINGS: Int = 2
}

class Account(val accountType: Int, var transactions: ListBuffer[Transaction] = ListBuffer()) {
abstract class Account(val transactions: ListBuffer[Transaction] = ListBuffer()) {

def deposit(amount: Double) {
if (amount <= 0)
throw new IllegalArgumentException("amount must be greater than zero")
else
transactions += Transaction(amount)
transactions += new RealTransaction(amount)
}

def withdraw(amount: Double) {
if (amount <= 0)
throw new IllegalArgumentException("amount must be greater than zero")
else
transactions += Transaction(-amount)
transactions += new RealTransaction(-amount)
}

def interestEarned: Double = {
val amount: Double = sumTransactions()
accountType match {
case Account.SAVINGS =>
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
case _ =>
amount * 0.001
}
val amount: Double = sumTransactions
calculateInterest(amount)
}

def addTransaction(t: Transaction): Unit = transactions += t

def sumTransactions: Double = transactions.map(_.amount).sum

protected def calculateInterest(amount: Double): Double

}

case class CheckingAccount(override val transactions: ListBuffer[Transaction] = ListBuffer()) extends Account(transactions) {
def calculateInterest(amount: Double) = amount * 0.001
override def toString = "Checking Account"
}

case class SavingsAccount(override val transactions: ListBuffer[Transaction] = ListBuffer()) extends Account(transactions) {
def calculateInterest(amount: Double) = {
if (amount <= 1000) amount * 0.001
else 1 + (amount - 1000) * 0.002
}
override def toString = "Savings Account"
}

def sumTransactions(checkAllTransactions: Boolean = true): Double = transactions.map(_.amount).sum
case class MaxiSavingsAccount(override val transactions: ListBuffer[Transaction] = ListBuffer()) extends Account(transactions) {
def calculateInterest(amount: Double) = {
/**
if (amount <= 1000) amount * 0.02
else if (amount <= 2000) 20 + (amount - 1000) * 0.05
else 70 + (amount - 2000) * 0.1
*/
if ( hasWithdrawalInPastTenDays )
amount * 0.001
else
amount * 0.05
}

override def toString = "Maxi Savings Account"

def hasWithdrawalInPastTenDays: Boolean = {
val now = DateProvider.now

val cal = Calendar.getInstance()
cal.setTime(now)
cal.add(Calendar.DATE, -10)
val tenDaysAgo = cal.getTime

transactions.exists( t => t.transactionDate.after(tenDaysAgo) && t.amount < 0.0 )
}
}
17 changes: 5 additions & 12 deletions src/main/scala/com/abc/Bank.scala
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,15 @@ class Bank {
def totalInterestPaid: Double = {
var total: Double = 0
for (c <- customers) total += c.totalInterestEarned
return total
total
}

def getFirstCustomer: String = {
try {
customers = null
customers(0).name
}
catch {
case e: Exception => {
e.printStackTrace
return "Error"
}
}
if(customers.nonEmpty )
customers.head.name
else
"Error"
}

}


23 changes: 14 additions & 9 deletions src/main/scala/com/abc/Customer.scala
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,16 @@ class Customer(val name: String, var accounts: ListBuffer[Account] = ListBuffer(
//JIRA-123 Change by Joe Bloggs 29/7/1988 start
var statement: String = null //reset statement to null here
//JIRA-123 Change by Joe Bloggs 29/7/1988 end
val totalAcrossAllAccounts = accounts.map(_.sumTransactions()).sum
val totalAcrossAllAccounts = accounts.map(_.sumTransactions).sum
statement = f"Statement for $name\n" +
accounts.map(statementForAccount).mkString("\n", "\n\n", "\n") +
s"\nTotal In All Accounts ${toDollars(totalAcrossAllAccounts)}"
statement
}

private def statementForAccount(a: Account): String = {
val accountType = a.accountType match {
case Account.CHECKING =>
"Checking Account\n"
case Account.SAVINGS =>
"Savings Account\n"
case Account.MAXI_SAVINGS =>
"Maxi Savings Account\n"
}
val accountType = a.toString + "\n"

val transactionSummary = a.transactions.map(t => withdrawalOrDepositText(t) + " " + toDollars(t.amount.abs))
.mkString(" ", "\n ", "\n")
val totalSummary = s"Total ${toDollars(a.transactions.map(_.amount).sum)}"
Expand All @@ -50,5 +44,16 @@ class Customer(val name: String, var accounts: ListBuffer[Account] = ListBuffer(
}

private def toDollars(number: Double): String = f"$$$number%.2f"

def transfer(fromAccount: Account, toAccount:Account, amount: Double) = {
if( ! accounts.contains(fromAccount) || ! accounts.contains(toAccount) ) {
throw new IllegalArgumentException("cannot tranfers between accounts not owned")
}
if( amount <= 0.0 ) {
throw new IllegalArgumentException("transfer amount must be greater than zero")
}
fromAccount.withdraw(amount)
toAccount.deposit(amount)
}
}

11 changes: 2 additions & 9 deletions src/main/scala/com/abc/DateProvider.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,10 @@ import java.util.Calendar
import java.util.Date

object DateProvider {
def getInstance: DateProvider = {
if (instance == null) instance = new DateProvider
instance
}

private var instance: DateProvider = null
}

class DateProvider {
def now: Date = {
return Calendar.getInstance.getTime
Calendar.getInstance.getTime
}
}


13 changes: 11 additions & 2 deletions src/main/scala/com/abc/Transaction.scala
Original file line number Diff line number Diff line change
@@ -1,6 +1,15 @@
package com.abc

case class Transaction(var amount: Double) {
val transactionDate = DateProvider.getInstance.now
import java.util.Date

trait Transaction {
def amount: Double
def transactionDate: Date
}

case class RealTransaction(var amount: Double) extends Transaction {
def transactionDate = DateProvider.now
}

case class FakeTransaction(var amount: Double, var transactionDate: Date) extends Transaction

68 changes: 61 additions & 7 deletions src/test/scala/com/abc/BankTest.scala
Original file line number Diff line number Diff line change
@@ -1,19 +1,36 @@
package com.abc

import org.scalatest.{Matchers, FlatSpec}
import java.util.Date
import java.util.Calendar

class BankTest extends FlatSpec with Matchers {

"Bank" should "customer summary" in {
val bank: Bank = new Bank
var john: Customer = new Customer("John").openAccount(new Account(Account.CHECKING))
val john: Customer = new Customer("John").openAccount(new CheckingAccount())
bank.addCustomer(john)
bank.customerSummary should be("Customer Summary\n - John (1 account)")
john.openAccount(new SavingsAccount())
val jane: Customer = new Customer("Jane").openAccount(new MaxiSavingsAccount())
bank.addCustomer(jane)
bank.customerSummary should be("Customer Summary\n - John (2 accounts)\n - Jane (1 account)")
}

it should "first customer" in {
val bank: Bank = new Bank
bank.getFirstCustomer should be("Error")

val john: Customer = new Customer("John").openAccount(new CheckingAccount())
bank.addCustomer(john)
val jane: Customer = new Customer("Jane").openAccount(new MaxiSavingsAccount())
bank.addCustomer(jane)
bank.getFirstCustomer should be("John")
}

it should "checking account" in {
val bank: Bank = new Bank
val checkingAccount: Account = new Account(Account.CHECKING)
val checkingAccount: Account = new CheckingAccount()
val bill: Customer = new Customer("Bill").openAccount(checkingAccount)
bank.addCustomer(bill)
checkingAccount.deposit(100.0)
Expand All @@ -22,18 +39,55 @@ class BankTest extends FlatSpec with Matchers {

it should "savings account" in {
val bank: Bank = new Bank
val checkingAccount: Account = new Account(Account.SAVINGS)
bank.addCustomer(new Customer("Bill").openAccount(checkingAccount))
checkingAccount.deposit(1500.0)
val savingsAccount: Account = new SavingsAccount()
bank.addCustomer(new Customer("Bill").openAccount(savingsAccount))
savingsAccount.deposit(1500.0)
bank.totalInterestPaid should be(2.0)
savingsAccount.withdraw(700)
bank.totalInterestPaid should be(0.8)
}

it should "maxi savings account" in {
val bank: Bank = new Bank
val checkingAccount: Account = new Account(Account.MAXI_SAVINGS)
bank.addCustomer(new Customer("Bill").openAccount(checkingAccount))
val maxiSavingsAccount: Account = new MaxiSavingsAccount()
bank.addCustomer(new Customer("Bill").openAccount(maxiSavingsAccount))
/**
checkingAccount.deposit(3000.0)
bank.totalInterestPaid should be(170.0)
checkingAccount.withdraw(1200.0)
bank.totalInterestPaid should be(60.0)
checkingAccount.withdraw(1200.0)
bank.totalInterestPaid should be(12.0)
*/
val now:Date = DateProvider.now
maxiSavingsAccount.addTransaction(new FakeTransaction(1000, now))
bank.totalInterestPaid should be(50)

val cal = Calendar.getInstance()
cal.setTime(now)
cal.add(Calendar.DATE, -11)
val elevenDaysAgo = cal.getTime

maxiSavingsAccount.addTransaction(new FakeTransaction(-200, elevenDaysAgo))
bank.totalInterestPaid should be(40)

cal.add(Calendar.DATE, 3)
val eightDaysAgo = cal.getTime

maxiSavingsAccount.addTransaction(new FakeTransaction(-200, eightDaysAgo))

bank.totalInterestPaid should be(0.6)
}

it should "total interest" in {
val bank: Bank = new Bank
val checkingAccount: Account = new CheckingAccount()
val bill: Customer = new Customer("Bill").openAccount(checkingAccount)
bank.addCustomer(bill)
checkingAccount.deposit(100.0)
val savingsAccount: Account = new SavingsAccount()
bank.addCustomer(new Customer("Carol").openAccount(savingsAccount))
savingsAccount.deposit(1500.0)
bank.totalInterestPaid should be(2.1)
}
}
43 changes: 32 additions & 11 deletions src/test/scala/com/abc/CustomerTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import org.scalatest.{Matchers, FlatSpec}

class CustomerTest extends FlatSpec with Matchers {
"Customer" should "statement" in {
val checkingAccount: Account = new Account(Account.CHECKING)
val savingsAccount: Account = new Account(Account.SAVINGS)
val checkingAccount: Account = new CheckingAccount()
val savingsAccount: Account = new SavingsAccount()
val henry: Customer = new Customer("Henry").openAccount(checkingAccount).openAccount(savingsAccount)
checkingAccount.deposit(100.0)
savingsAccount.deposit(4000.0)
Expand All @@ -17,19 +17,40 @@ class CustomerTest extends FlatSpec with Matchers {
}

it should "testOneAccount" in {
val oscar: Customer = new Customer("Oscar").openAccount(new Account(Account.SAVINGS))
val oscar: Customer = new Customer("Oscar").openAccount(new SavingsAccount())
oscar.numberOfAccounts should be(1)
}

it should "testTwoAccount" in {
val oscar: Customer = new Customer("Oscar").openAccount(new Account(Account.SAVINGS))
oscar.openAccount(new Account(Account.CHECKING))
oscar.openAccount(new CheckingAccount())
oscar.numberOfAccounts should be(2)
}

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)
it should "throw IllegalArgumentException for negative withdrawal/deposit" in {
val checkingAccount: Account = new CheckingAccount()
a [IllegalArgumentException] should be thrownBy {
checkingAccount.withdraw(-1000)
}
a [IllegalArgumentException] should be thrownBy {
checkingAccount.deposit(-1000)
}
}

it should "transfer" in {
val checkingAccount: Account = new CheckingAccount()
checkingAccount.deposit(1000.0)
val savingsAccount: Account = new SavingsAccount()
savingsAccount.deposit(200.0)
val henry: Customer = new Customer("Henry")

a [IllegalArgumentException] should be thrownBy {
henry.transfer(checkingAccount, savingsAccount, 500.0)
}

henry.openAccount(checkingAccount)
henry.openAccount(savingsAccount)
henry.transfer(checkingAccount, savingsAccount, 500.0)

checkingAccount.sumTransactions should be(500.0)
savingsAccount.sumTransactions should be (700.0)
}

}
2 changes: 1 addition & 1 deletion src/test/scala/com/abc/TransactionTest.scala
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import org.scalatest.{FlatSpec, Matchers}

class TransactionTest extends FlatSpec with Matchers {
"Transaction" should "type" in {
val t = new Transaction(5)
val t = new RealTransaction(5)
t.isInstanceOf[Transaction] should be(true)
}
}