Buckazoid
Sensible money library
Named after SpaceQuest money.
Scala library providing Money Type safe DLS, exchange rate conversion with Dates with support for external services calls, easy money arithmetic and more.
Installation
To use Buckazoid in your SBT project add the following dependency to your build.
"com.vatbox" %% "buckazoid" % "LATEST_VERSION"
Where you replace LATEST_VERSION with the version shown in this image:
To use Buckazoid in your Maven / Gradle project look at the bintray repository
Usage
scala> import com.vatbox.money._
import java.time.Instant
import scala.concurrent._
import scala.concurrent.duration._
import scala.concurrent.ExecutionContext.Implicits.global
scala> USD(10)
res0: com.vatbox.money.Money[com.vatbox.money.USD.Key] = 10 USD
scala> EUR(50)
res1: com.vatbox.money.Money[com.vatbox.money.EUR.Key] = 50 EUR
scala> 5(USD) + 10(USD) * 2 + USD(20) + Money(5, USD)
res2: com.vatbox.money.Money[com.vatbox.money.USD.Key] = 50 USD
scala> implicit object ExchangeRateDemo extends ExchangeRate {
override def convert(base: Currency {type Key <: Currency.Key}, counter: Currency {type Key <: Currency.Key}, amount: BigDecimal, exchangeDate: Instant): Future[BigDecimal] = {
(base, counter) match {
case (f, b) if f == b ⇒ Future.successful { amount }
case (ILS, USD) ⇒ convert(USD, ILS, 1, exchangeDate) map (1 / _ * amount)
case (USD, ILS) ⇒ Future.successful { 5 * amount }
case (ILS, EUR) ⇒ convert(EUR, ILS, 1, exchangeDate) map (1 / _ * amount)
case (EUR, ILS) ⇒ Future.successful { 10 * amount }
case (EUR, USD) ⇒ convert(EUR, ILS, 1, exchangeDate) flatMap {ratio ⇒ convert(ILS, USD, ratio * amount, exchangeDate)}
case (USD, EUR) ⇒ convert(USD, ILS, 1, exchangeDate) flatMap {ratio ⇒ convert(ILS, EUR, ratio * amount, exchangeDate)}
case (Currency("TST",_,_,_,_,_,_), USD) ⇒ Future.successful { 99 * amount }
case (USD, Currency("TST",_,_,_,_,_,_)) ⇒ convert(Currency("TST"), USD, 1, exchangeDate) map (1 / _ * amount)
case _ ⇒ Future.failed {
ExchangeRateException(s"Fail to convert $base to $counter")
}
}
}
}
defined object ExchangeRateDemo
scala> val total = EUR(5) + USD(10) + ILS(20) at Instant.now
total: scala.concurrent.Future[com.vatbox.money.Money[com.vatbox.money.EUR.Key]] = Future(<not completed>)
total foreach println
12.0 EUR
scala> EUR(5) + USD(10) + ILS(20) in ILS at Instant.now foreach println
120 ILS
scala> val usd2eur = USD to EUR at Instant.now
usd2eur: com.vatbox.money.CurrencyExchangeRate[com.vatbox.money.USD.Key,com.vatbox.money.EUR.Key] = CurrencyExchangeRate(Currency(USD,United States dollar,$,2,None,None,None),Currency(EUR,Euro,€,2,None,None,None),2018-05-30T11:30:52.728Z)
scala> val tenUsdInEur = usd2eur convert (10)
TenUsdInEur: scala.concurrent.Future[com.vatbox.money.Money[com.vatbox.money.EUR.Key]] = Future(<not completed>)
scala> tenUsdInEur
scala.concurrent.Future[com.vatbox.money.Money[com.vatbox.money.EUR.Key]] = Future(Success(5.0 EUR))
scala> TenUsdInEur foreach println
5.0 EUR
scala> usd2eur.rate foreach println
0.5
scala> val eur2usd = usd2eur.inverse
eur2usd: com.vatbox.money.CurrencyExchangeRate[com.vatbox.money.EUR.Key,com.vatbox.money.USD.Key] = CurrencyExchangeRate(Currency(EUR,Euro,€,2,None,None,None),Currency(USD,United States dollar,$,2,None,None,None),2018-05-30T11:30:52.728Z)
scala> eur2usd.rate foreach println
2.0
scala> val handerEurToUSD = 100(EUR) in USD
handerEurToUSD: com.vatbox.money.MoneyExchange[com.vatbox.money.USD.Key] = MoneyExchange(Currency(USD,United States dollar,$,2,None,None,None),List(100 EUR))
scala> handerEurToUSD at Instant.now foreach println
200.0 USD
scala> 100.2(EUR) ==~ 100(EUR) +- 0.5
res8: Boolean = true
scala> 10(USD) >~ 9(USD) ± 2
res9: Boolean = false
scala> 50.0(EUR) === (100(USD) in EUR) at Instant.now foreach println
true
openexchange as ExchangeRate:
UsingAdd the following dependency to your build
"com.vatbox" %% "buckazoid" % "LATEST_VERSION"
scala> import com.vatbox.money.contrib.exchangerate._
import play.api.libs.ws.ahc.StandaloneAhcWSClient
import akka.actor.ActorSystem
import akka.stream.ActorMaterializer
implicit val system = ActorSystem()
implicit val materializer = ActorMaterializer()
scala> implicit val client = PlayOpenExchangeRates(StandaloneAhcWSClient(), "https://openexchangerates.org/api/historical/", "[OPEN_EXCHANGE_RATES_KEY]")
scala> val total = EUR(5) + USD(10) + ILS(20) at Instant.parse("2018-06-18T00:00:00Z")
total: scala.concurrent.Future[com.vatbox.money.Money[com.vatbox.money.EUR.Key]] = Future(<not completed>)
scala> total foreach println
18.355240 EUR