mirror of
https://github.com/corda/corda.git
synced 2024-12-23 14:52:29 +00:00
Add functions for converting Amount to/from decimal
Add new functions for converting amounts to/from decimal representation. Also adds clarification that the constructor which takes in a BigDecimal drops any fractional part. Signed-off-by: Ross Nicoll <ross.nicoll@r3.com>
This commit is contained in:
parent
70bf16be99
commit
c1d5e5c82e
@ -10,6 +10,7 @@ import com.fasterxml.jackson.databind.annotation.JsonDeserialize
|
||||
import com.fasterxml.jackson.databind.annotation.JsonSerialize
|
||||
import com.google.common.annotations.VisibleForTesting
|
||||
import java.math.BigDecimal
|
||||
import java.math.BigInteger
|
||||
import java.time.DayOfWeek
|
||||
import java.time.LocalDate
|
||||
import java.time.format.DateTimeFormatter
|
||||
@ -34,6 +35,19 @@ import java.util.*
|
||||
* @param T the type of the token, for example [Currency].
|
||||
*/
|
||||
data class Amount<T>(val quantity: Long, val token: T) : Comparable<Amount<T>> {
|
||||
companion object {
|
||||
/**
|
||||
* Build an amount from a decimal representation. For example, with an input of "12.34" GBP,
|
||||
* returns an amount with a quantity of "1234".
|
||||
*
|
||||
* @see Amount<Currency>.toDecimal
|
||||
*/
|
||||
fun fromDecimal(quantity: BigDecimal, currency: Currency) : Amount<Currency> {
|
||||
val longQuantity = quantity.movePointRight(currency.defaultFractionDigits).toLong()
|
||||
return Amount(longQuantity, currency)
|
||||
}
|
||||
}
|
||||
|
||||
init {
|
||||
// Negative amounts are of course a vital part of any ledger, but negative values are only valid in certain
|
||||
// contexts: you cannot send a negative amount of cash, but you can (sometimes) have a negative balance.
|
||||
@ -41,7 +55,12 @@ data class Amount<T>(val quantity: Long, val token: T) : Comparable<Amount<T>> {
|
||||
require(quantity >= 0) { "Negative amounts are not allowed: $quantity" }
|
||||
}
|
||||
|
||||
constructor(amount: BigDecimal, currency: T) : this(amount.toLong(), currency)
|
||||
/**
|
||||
* Construct the amount using the given decimal value as quantity. Any fractional part
|
||||
* is discarded. To convert and use the fractional part, see [fromDecimal].
|
||||
*/
|
||||
constructor(quantity: BigDecimal, token: T) : this(quantity.toLong(), token)
|
||||
constructor(quantity: BigInteger, token: T) : this(quantity.toLong(), token)
|
||||
|
||||
operator fun plus(other: Amount<T>): Amount<T> {
|
||||
checkCurrency(other)
|
||||
@ -70,6 +89,14 @@ data class Amount<T>(val quantity: Long, val token: T) : Comparable<Amount<T>> {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a currency [Amount] to a decimal representation. For example, with an amount with a quantity
|
||||
* of "1234" GBP, returns "12.34".
|
||||
*
|
||||
* @see Amount.Companion.fromDecimal
|
||||
*/
|
||||
fun Amount<Currency>.toDecimal() : BigDecimal = BigDecimal(quantity).movePointLeft(token.defaultFractionDigits)
|
||||
|
||||
fun <T> Iterable<Amount<T>>.sumOrNull() = if (!iterator().hasNext()) null else sumOrThrow()
|
||||
fun <T> Iterable<Amount<T>>.sumOrThrow() = reduce { left, right -> left + right }
|
||||
fun <T> Iterable<Amount<T>>.sumOrZero(currency: T) = if (iterator().hasNext()) sumOrThrow() else Amount(0, currency)
|
||||
|
26
core/src/test/kotlin/net/corda/core/contracts/AmountTests.kt
Normal file
26
core/src/test/kotlin/net/corda/core/contracts/AmountTests.kt
Normal file
@ -0,0 +1,26 @@
|
||||
package net.corda.core.contracts
|
||||
|
||||
import org.junit.Test
|
||||
import java.math.BigDecimal
|
||||
import kotlin.test.assertEquals
|
||||
|
||||
/**
|
||||
* Tests of the [Amount] class.
|
||||
*/
|
||||
class AmountTests {
|
||||
@Test
|
||||
fun basicCurrency() {
|
||||
val expected = 1000L
|
||||
val amount = Amount(expected, GBP)
|
||||
assertEquals(expected, amount.quantity)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun decimalConversion() {
|
||||
val quantity = 1234L
|
||||
val amount = Amount(quantity, GBP)
|
||||
val expected = BigDecimal("12.34")
|
||||
assertEquals(expected, amount.toDecimal())
|
||||
assertEquals(amount, Amount.fromDecimal(amount.toDecimal(), amount.token))
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user