From 5b2149d18be3931b67777ebedcc3b70f18fc5d22 Mon Sep 17 00:00:00 2001 From: Kazik Pogoda Date: Thu, 5 Dec 2024 22:36:14 +0100 Subject: [PATCH] helper methods for Money.Ratio obtained from String and Int (#1) --- api/xemantic-ai-money.api | 12 ++++++++++++ src/commonMain/kotlin/Money.kt | 9 +++++++++ src/commonTest/kotlin/MoneyRatioTest.kt | 26 +++++++++++++++++++++++++ src/commonTest/kotlin/MoneyTest.kt | 18 +++++++++++++++++ src/jvmMain/kotlin/JvmMoney.kt | 3 +++ src/nonJvmMain/kotlin/NonJvmMoney.kt | 13 ++++++++----- 6 files changed, 76 insertions(+), 5 deletions(-) diff --git a/api/xemantic-ai-money.api b/api/xemantic-ai-money.api index d434182..93f844e 100644 --- a/api/xemantic-ai-money.api +++ b/api/xemantic-ai-money.api @@ -5,6 +5,7 @@ public final class com/xemantic/ai/money/JvmMoney : com/xemantic/ai/money/Money public fun hashCode ()I public fun minus (Lcom/xemantic/ai/money/Money;)Lcom/xemantic/ai/money/Money; public fun plus (Lcom/xemantic/ai/money/Money;)Lcom/xemantic/ai/money/Money; + public fun times (I)Lcom/xemantic/ai/money/Money; public fun times (Lcom/xemantic/ai/money/Money$Ratio;)Lcom/xemantic/ai/money/Money; public fun times (Lcom/xemantic/ai/money/Money;)Lcom/xemantic/ai/money/Money; public fun toString ()Ljava/lang/String; @@ -16,6 +17,7 @@ public final class com/xemantic/ai/money/JvmMoneyKt { public static final fun getONE (Lcom/xemantic/ai/money/Money$Companion;)Lcom/xemantic/ai/money/Money; public static final fun getONE (Lcom/xemantic/ai/money/Money$Ratio$Companion;)Lcom/xemantic/ai/money/Money$Ratio; public static final fun getZERO (Lcom/xemantic/ai/money/Money$Companion;)Lcom/xemantic/ai/money/Money; + public static final fun toMoneyRatio (I)Lcom/xemantic/ai/money/Money$Ratio; } public abstract interface class com/xemantic/ai/money/Money { @@ -23,6 +25,7 @@ public abstract interface class com/xemantic/ai/money/Money { public abstract fun compareTo (Lcom/xemantic/ai/money/Money;)I public abstract fun minus (Lcom/xemantic/ai/money/Money;)Lcom/xemantic/ai/money/Money; public abstract fun plus (Lcom/xemantic/ai/money/Money;)Lcom/xemantic/ai/money/Money; + public abstract fun times (I)Lcom/xemantic/ai/money/Money; public abstract fun times (Lcom/xemantic/ai/money/Money$Ratio;)Lcom/xemantic/ai/money/Money; public abstract fun times (Lcom/xemantic/ai/money/Money;)Lcom/xemantic/ai/money/Money; } @@ -31,6 +34,10 @@ public final class com/xemantic/ai/money/Money$Companion { public final fun serializer ()Lkotlinx/serialization/KSerializer; } +public final class com/xemantic/ai/money/Money$DefaultImpls { + public static fun times (Lcom/xemantic/ai/money/Money;I)Lcom/xemantic/ai/money/Money; +} + public abstract interface class com/xemantic/ai/money/Money$Ratio { public static final field Companion Lcom/xemantic/ai/money/Money$Ratio$Companion; public abstract fun times (Lcom/xemantic/ai/money/Money;)Lcom/xemantic/ai/money/Money; @@ -40,6 +47,11 @@ public final class com/xemantic/ai/money/Money$Ratio$Companion { public final fun serializer ()Lkotlinx/serialization/KSerializer; } +public final class com/xemantic/ai/money/MoneyKt { + public static final fun getMoneyRatio (Ljava/lang/String;)Lcom/xemantic/ai/money/Money$Ratio; + public static final fun times (ILcom/xemantic/ai/money/Money;)Lcom/xemantic/ai/money/Money; +} + public final class com/xemantic/ai/money/serialization/MoneyRatioSerializer : kotlinx/serialization/KSerializer { public static final field INSTANCE Lcom/xemantic/ai/money/serialization/MoneyRatioSerializer; public fun deserialize (Lkotlinx/serialization/encoding/Decoder;)Lcom/xemantic/ai/money/Money$Ratio; diff --git a/src/commonMain/kotlin/Money.kt b/src/commonMain/kotlin/Money.kt index 02fe923..b1de47d 100644 --- a/src/commonMain/kotlin/Money.kt +++ b/src/commonMain/kotlin/Money.kt @@ -51,6 +51,10 @@ public interface Money { public operator fun times(ratio: Ratio): Money + public operator fun times( + scalar: Int + ): Money = this * scalar.toMoneyRatio() + public operator fun compareTo(money: Money): Int /** @@ -80,3 +84,8 @@ public expect fun Money.Companion.Ratio(value: String): Money.Ratio public expect val Money.Ratio.Companion.ONE: Money.Ratio +public val String.moneyRatio get() = Money.Ratio(this) + +public expect fun Int.toMoneyRatio(): Money.Ratio + +public operator fun Int.times(money: Money): Money = toMoneyRatio().times(money) diff --git a/src/commonTest/kotlin/MoneyRatioTest.kt b/src/commonTest/kotlin/MoneyRatioTest.kt index 7591701..1fdf00b 100644 --- a/src/commonTest/kotlin/MoneyRatioTest.kt +++ b/src/commonTest/kotlin/MoneyRatioTest.kt @@ -18,6 +18,7 @@ package com.xemantic.ai.money import com.xemantic.ai.money.test.shouldBe import kotlin.test.Test +import kotlin.test.assertFailsWith class MoneyRatioTest { @@ -26,6 +27,13 @@ class MoneyRatioTest { Money.Ratio("1.25").toString() shouldBe "1.25" } + @Test + fun `Should not create Money Ratio instance from invalid String`() { + assertFailsWith { + Money.Ratio("foo") + } + } + @Test fun `Should create Money Ratio instance with long fractional part`() { Money.Ratio("0.0000001").toString() shouldBe "0.0000001" @@ -43,4 +51,22 @@ class MoneyRatioTest { Money.Ratio("0.000001") * Money("3.0") shouldBe Money("0.000003") } + @Test + fun `Should convert valid string to Money Ratio`() { + "0.000001".moneyRatio shouldBe Money.Ratio("0.000001") + } + + @Test + fun `Should not convert invalid string to Money Ratio`() { + assertFailsWith { + "foo".moneyRatio + } + } + + @Test + fun `Should convert Int to Money Ratio`() { + 1.toMoneyRatio() shouldBe Money.Ratio("1") + 42.toMoneyRatio() shouldBe Money.Ratio("42") + } + } diff --git a/src/commonTest/kotlin/MoneyTest.kt b/src/commonTest/kotlin/MoneyTest.kt index c33eec3..fc86003 100644 --- a/src/commonTest/kotlin/MoneyTest.kt +++ b/src/commonTest/kotlin/MoneyTest.kt @@ -18,6 +18,7 @@ package com.xemantic.ai.money import com.xemantic.ai.money.test.shouldBe import kotlin.test.Test +import kotlin.test.assertFailsWith class MoneyTest { @@ -26,6 +27,13 @@ class MoneyTest { Money("42.50").toString() shouldBe "42.5" } + @Test + fun `Should not create Money instance from invalid String`() { + assertFailsWith { + Money.Ratio("foo") + } + } + @Test fun `Should create Money instance with long fractional part`() { Money("42.123456789").toString() shouldBe "42.123456789" @@ -84,4 +92,14 @@ class MoneyTest { (money3 < money1) shouldBe false } + @Test + fun `Should multiply Int and Money`() { + 2 * Money("2.25") shouldBe Money("4.5") + } + + @Test + fun `Should multiply Money and Int`() { + Money("2.25") * 2 shouldBe Money("4.5") + } + } diff --git a/src/jvmMain/kotlin/JvmMoney.kt b/src/jvmMain/kotlin/JvmMoney.kt index b0289ab..9c536ab 100644 --- a/src/jvmMain/kotlin/JvmMoney.kt +++ b/src/jvmMain/kotlin/JvmMoney.kt @@ -98,3 +98,6 @@ public actual fun Money.Companion.Ratio( @Suppress("ObjectPropertyName") private val _RATIO_ONE = JvmMoney.JvmRatio(BigDecimal.ONE) public actual val Money.Ratio.Companion.ONE: Money.Ratio get() = _RATIO_ONE + +public actual fun Int.toMoneyRatio(): Money.Ratio = + JvmMoney.JvmRatio(BigDecimal(this)) diff --git a/src/nonJvmMain/kotlin/NonJvmMoney.kt b/src/nonJvmMain/kotlin/NonJvmMoney.kt index 47983be..743e5b8 100644 --- a/src/nonJvmMain/kotlin/NonJvmMoney.kt +++ b/src/nonJvmMain/kotlin/NonJvmMoney.kt @@ -33,7 +33,7 @@ public class NonJvmMoney(private val value: BigDecimal) : Money { ) override fun times(ratio: Money.Ratio): Money = NonJvmMoney( - (value * (ratio as NativeRatio).value) + (value * (ratio as NonJvmRatio).value) ) override fun compareTo( @@ -52,7 +52,7 @@ public class NonJvmMoney(private val value: BigDecimal) : Money { override fun hashCode(): Int = value.hashCode() - internal class NativeRatio(internal val value: BigDecimal) : Money.Ratio { + internal class NonJvmRatio(internal val value: BigDecimal) : Money.Ratio { override fun times(amount: Money): Money = NonJvmMoney( (value * (amount as NonJvmMoney).value) @@ -65,7 +65,7 @@ public class NonJvmMoney(private val value: BigDecimal) : Money { override fun equals( other: Any? ): Boolean = (other != null) - && (other is NativeRatio) + && (other is NonJvmRatio) && (value == other.value) override fun hashCode(): Int = value.hashCode() @@ -88,10 +88,13 @@ public actual val Money.Companion.ONE: Money get() = _ONE public actual fun Money.Companion.Ratio( value: String -): Money.Ratio = NonJvmMoney.NativeRatio( +): Money.Ratio = NonJvmMoney.NonJvmRatio( BigDecimal.parseString(value) ) @Suppress("ObjectPropertyName") -private val _RATIO_ONE = NonJvmMoney.NativeRatio(BigDecimal.ONE) +private val _RATIO_ONE = NonJvmMoney.NonJvmRatio(BigDecimal.ONE) public actual val Money.Ratio.Companion.ONE: Money.Ratio get() = _RATIO_ONE + +public actual fun Int.toMoneyRatio(): Money.Ratio = + NonJvmMoney.NonJvmRatio(BigDecimal.fromInt(this))