Add money object with generator and builder for operators the values from builder with batch and remove unused files and functions was updated for some operators

This commit is contained in:
Sambo Chea 2021-02-08 18:53:46 +07:00
parent 3a7141cf76
commit 980b741ee9
5 changed files with 201 additions and 74 deletions

View File

@ -65,7 +65,7 @@ object MoneyConfig {
MoneyConfig.config.put(currency, value)
}
} else {
throw MoneyCurrencyStateException("money config format is not valid!")
throw MoneyCurrencyStateException("money config format $temp is not valid!")
}
}
}
@ -107,8 +107,8 @@ object MoneyConfig {
@Throws(MoneyCurrencyStateException::class)
fun getRate(currency: StdMoney.Currency): Double {
return getConfig()[currency.getCurrency().toUpperCase()]
?: throw MoneyCurrencyStateException("money currency $currency is not valid!")
return getConfig()[currency.getCurrency().toUpperCase().trim()]
?: throw MoneyCurrencyStateException("money currency ${currency.getCurrency()} is not valid!")
}
class MoneyConfigProperties(

View File

@ -1,15 +0,0 @@
package com.cubetiqs.money
import java.io.Serializable
/**
* @author sombochea <Sambo Chea>
* @email sombochea@cubetiqs.com>
* @date 08/02/21
* @since 1.0
*/
data class MoneyHistory(
val valueOn: String? = null,
val valueOf: String? = null,
val currency: String? = null
) : Serializable

View File

@ -1,47 +1,143 @@
package com.cubetiqs.money
import java.io.Serializable
import java.util.*
sealed class MoneyObject : Serializable, StdMoney {
private var value: Double = 0.0
private var currency: StdMoney.Currency = MoneyCurrency.USD
private val moneyStates: MutableMap<MoneyCurrency, MoneyState> = mutableMapOf()
constructor(value: Double, currency: MoneyCurrency) {
this.value = value
this.currency = currency
isComputed = false
}
/**
* Check if computed, set it to true. Because we no need to add the same value again after once
* computed.
/**
* Money Object Generator (Quick building the money)
*
* @since 1.0
* @author sombochea
*/
@Transient
var isComputed = false
private set
@Transient
var isInit = false
private set
/** Calculate the value. Must be call after complete add money. */
fun compute(): MoneyObject = apply {
class MoneyObject(
val value: Double,
val currency: String,
var operator: MoneyOperator? = null,
var with: MoneyObject? = null,
) : StdMoney {
fun appendWith(with: MoneyObject?) {
if (this.with == null) {
this.with = with
} else {
this.with!!.appendWith(with)
}
}
companion object {
@JvmStatic
private fun defaultCurrency(): StdMoney.Currency {
return MoneyExchangeUtils.getBaseCurrency()
}
override fun getMoneyCurrency(): StdMoney.Currency {
return StdMoney.initCurrency(currency)
}
override fun getMoneyValue(): Double {
return value
}
override fun getMoneyCurrency(): StdMoney.Currency {
return currency
private fun generate(): StdMoney {
if (this.with != null) {
val withGenerated = this.with!!.generate()
return when (operator) {
MoneyOperator.PLUS -> this plusWith withGenerated
MoneyOperator.MINUS -> this minusWith withGenerated
MoneyOperator.DIVIDE -> this divideWith withGenerated
MoneyOperator.MULTIPLY -> this multiplyWith withGenerated
// if operator is null or empty with default Plus operator
else -> this plusWith withGenerated
}
}
return StdMoney.initMoney(value, currency = StdMoney.initCurrency(currency))
}
fun compute(): StdMoney {
return generate()
}
override fun toString(): String {
return "MoneyObject(value=$value, currency='$currency', operator=$operator, with=$with)"
}
enum class MoneyOperator {
// (+)
PLUS,
// (-)
MINUS,
// (/)
DIVIDE,
// (*)
MULTIPLY;
companion object {
fun operator(value: Char?): MoneyOperator {
return try {
when (value!!) {
'+' -> PLUS
'-' -> MINUS
'/' -> DIVIDE
'*' -> MULTIPLY
else -> throw IllegalArgumentException("operator not found with value: $value!")
}
} catch (ex: Exception) {
throw IllegalArgumentException("operator not found!")
}
}
}
}
class MoneyGeneratorBuilder {
private var currency: String? = null
private val withs: MutableCollection<MoneyObject> = LinkedList()
fun withCurrency(currency: String) = apply {
this.currency = currency
}
fun with(`object`: MoneyObject) = apply {
this.withs.add(`object`)
}
fun with(value: Double, currency: String, operator: MoneyOperator = MoneyOperator.PLUS) = apply {
this.with(
MoneyObject(
value, currency, operator
)
)
}
fun with(value: Double, currency: String, operator: Char) = apply {
this.with(
MoneyObject(
value, currency, MoneyOperator.operator(operator)
)
)
}
fun build(): MoneyObject {
val first: MoneyObject
if (this.currency.isNullOrEmpty() && withs.isNotEmpty()) {
first = withs.first()
withs.remove(first)
} else {
first = MoneyObject(
value = 0.0,
operator = MoneyOperator.PLUS,
currency = this.currency ?: MoneyCurrency.USD.getCurrency()
)
}
withs.forEach { with ->
first.appendWith(with)
}
return first
}
override fun toString(): String {
return "MoneyGeneratorBuilder(currency=$currency, withs=$withs)"
}
}
companion object {
fun builder() = MoneyGeneratorBuilder()
}
}

View File

@ -1,15 +0,0 @@
package com.cubetiqs.money
import java.io.Serializable
/**
* @author sombochea <Sambo Chea>
* @email sombochea@cubetiqs.com
* @date 08/02/21
* @since 1.0
*/
data class MoneyState(
var value: String? = null,
var currency: String? = null,
var history: MoneyHistory? = null
) : Serializable

View File

@ -3,18 +3,31 @@ import org.junit.Assert
import org.junit.Test
class MoneyTests {
@Test
fun exchange_2usd_to_khr_test() {
private fun initMoneyConfig() {
applyMoneyConfig {
setProperties(buildMoneyConfigProperties {
setDeliEqual(':')
setDeliSplit(',')
})
// parse("USD:1,KHR:4000")
// appendRate("usd", 1.0)
// appendRate("khr", 4000.0)
fromJson(MyBatchRates.getJsonRates())
}
}
@Test
fun exchange_2usd_to_khr_test() {
initMoneyConfig()
// applyMoneyConfig {
// setProperties(buildMoneyConfigProperties {
// setDeliEqual(':')
// setDeliSplit(',')
// })
// // parse("USD:1,KHR:4000")
// // appendRate("usd", 1.0)
// // appendRate("khr", 4000.0)
// fromJson(MyBatchRates.getJsonRates())
// }
// Is valid for money config?
Assert.assertTrue(MoneyConfig.isValid())
@ -37,8 +50,56 @@ class MoneyTests {
object MyBatchRates {
fun getJsonRates(): String {
return """
{"USD": 1.0,"KHR": 4000.0}
{"USD": 1.0,"KHR": 4000.0, "eur": 0.5}
""".trimIndent()
}
}
@Test
fun moneyGenerator() {
initMoneyConfig()
val moneyGen = MoneyObject(
value = 1.0,
currency = "usd",
operator = MoneyObject.MoneyOperator.PLUS,
with = MoneyObject(
value = 8000.0,
currency = "khr",
operator = MoneyObject.MoneyOperator.MINUS,
with = MoneyObject(
value = 1000.0,
currency = "khr",
)
)
)
val result = moneyGen.compute()
Assert.assertEquals(2.75, result.getMoneyValue(), 0.0)
}
@Test
fun moneyGeneratorBuilder() {
initMoneyConfig()
val expected = 72000.0
val builder = MoneyObject.builder()
.with(10.0, "usd", '+')
.with(1.5, "eur", '+')
.with(8000.0, "khr")
.with(10000.0, "khr")
.with(2000.0, "khr")
.with(.5, "eur", '-')
.with(1.0, "usd")
.withCurrency("khr")
.build()
val result = builder.compute()
println(result)
Assert.assertEquals(expected, result.getMoneyValue(), 0.0)
}
}