From dc3c99039342a060ce97e5e0be8f2d83c7c3cb96 Mon Sep 17 00:00:00 2001 From: Taush Sampley Date: Thu, 12 Sep 2024 12:50:52 -0500 Subject: [PATCH 1/5] Create naive currency unit test --- .../business/CurrencyUnitTest.kt | 84 +++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 core/entities/src/commonTest/kotlin/org.pointyware.xyz.core.entities/business/CurrencyUnitTest.kt diff --git a/core/entities/src/commonTest/kotlin/org.pointyware.xyz.core.entities/business/CurrencyUnitTest.kt b/core/entities/src/commonTest/kotlin/org.pointyware.xyz.core.entities/business/CurrencyUnitTest.kt new file mode 100644 index 00000000..0ba83c82 --- /dev/null +++ b/core/entities/src/commonTest/kotlin/org.pointyware.xyz.core.entities/business/CurrencyUnitTest.kt @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2024 Pointyware. Use of this software is governed by the GPL-3.0 license. + */ + +package org.pointyware.xyz.core.entities.business + +import kotlin.test.Test +import kotlin.test.assertEquals + +/** + * + */ +class CurrencyUnitTest { + + data class FormattingCase( + val amount: Long, + val form: Currency.Form, + val expected: String + ) + + @Test + fun testSimpleForm() { + listOf( + FormattingCase( + 100, + Currency.Form.usDollars, + "$100" + ), + FormattingCase( + 56, + Currency.Form.usDollars, + "$56" + ), + ).forEach { (amount, form, expected) -> + val currency = Currency(amount, form) + + val string = currency.format() + + assertEquals(expected, string) + } + } + + data class ComparisonCase( + val amount1: Long, + val form1: Currency.Form, + val amount2: Long, + val form2: Currency.Form, + val expected: Int + ) + + @Test + fun `comparison should `() { + listOf( + ComparisonCase( + 1, + Currency.Form.usDollars, + 100, + Currency.Form.usDollarCents, + 0 + ), + ComparisonCase( + 56, + Currency.Form.usDollars, + 5610, + Currency.Form.usDollarCents, + 1 + ), + ComparisonCase( + 56, + Currency.Form.usDollarCents, + 54, + Currency.Form.usDollarCents, + -1 + ), + ).forEach { (amount1, form1, amount2, form2, expected) -> + + val left = Currency(amount1, form1) + val right = Currency(amount2, form2) + val comparison = left.compareTo(right) + + assertEquals(expected, comparison) + } + } +} From 4df871e7cd19cede1c50631665f715c0d0ec9988 Mon Sep 17 00:00:00 2001 From: Taush Sampley Date: Thu, 12 Sep 2024 12:51:02 -0500 Subject: [PATCH 2/5] Add dollars extension function --- core/entities/src/commonMain/kotlin/business/Currency.kt | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/core/entities/src/commonMain/kotlin/business/Currency.kt b/core/entities/src/commonMain/kotlin/business/Currency.kt index 7e3e21a7..c5b0588c 100644 --- a/core/entities/src/commonMain/kotlin/business/Currency.kt +++ b/core/entities/src/commonMain/kotlin/business/Currency.kt @@ -78,6 +78,12 @@ interface Currency: Comparable { decimalPlaces = 2, centsPerUnit = 1, ) + + /* + TODO: Add currencies as different areas are supported by the application + 1. currency conversion service will be needed; can't use comparable directly + 2. currency exchange rates will be needed + */ } } } @@ -98,4 +104,5 @@ fun Currency(amount: Long, form: Currency.Form): Currency { return SimpleCurrency(amount, form) } +fun Long.dollars() = Currency(this, Currency.Form.usDollars) fun Long.dollarCents() = Currency(this, Currency.Form.usDollarCents) From 3eff012646d684118bdfcdad28110c413415ee0f Mon Sep 17 00:00:00 2001 From: Taush Sampley Date: Thu, 12 Sep 2024 12:53:09 -0500 Subject: [PATCH 3/5] Add extension function tests --- .../business/CurrencyUnitTest.kt | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/core/entities/src/commonTest/kotlin/org.pointyware.xyz.core.entities/business/CurrencyUnitTest.kt b/core/entities/src/commonTest/kotlin/org.pointyware.xyz.core.entities/business/CurrencyUnitTest.kt index 0ba83c82..c676a3b7 100644 --- a/core/entities/src/commonTest/kotlin/org.pointyware.xyz.core.entities/business/CurrencyUnitTest.kt +++ b/core/entities/src/commonTest/kotlin/org.pointyware.xyz.core.entities/business/CurrencyUnitTest.kt @@ -81,4 +81,22 @@ class CurrencyUnitTest { assertEquals(expected, comparison) } } + + @Test + fun `dollars should return a currency with the correct form`() { + val amount = 100L + val currency = amount.dollars() + + assertEquals(amount, currency.amount) + assertEquals(Currency.Form.usDollars, currency.form) + } + + @Test + fun `cents should return a currency with the correct form`() { + val amount = 100L + val currency = amount.dollarCents() + + assertEquals(amount, currency.amount) + assertEquals(Currency.Form.usDollarCents, currency.form) + } } From f2aa998184cceb1ea30e6cd3ec82518b58696148 Mon Sep 17 00:00:00 2001 From: Taush Sampley Date: Thu, 12 Sep 2024 12:59:39 -0500 Subject: [PATCH 4/5] Fix reversed test expectations --- .../business/CurrencyUnitTest.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/entities/src/commonTest/kotlin/org.pointyware.xyz.core.entities/business/CurrencyUnitTest.kt b/core/entities/src/commonTest/kotlin/org.pointyware.xyz.core.entities/business/CurrencyUnitTest.kt index c676a3b7..92c25548 100644 --- a/core/entities/src/commonTest/kotlin/org.pointyware.xyz.core.entities/business/CurrencyUnitTest.kt +++ b/core/entities/src/commonTest/kotlin/org.pointyware.xyz.core.entities/business/CurrencyUnitTest.kt @@ -63,14 +63,14 @@ class CurrencyUnitTest { Currency.Form.usDollars, 5610, Currency.Form.usDollarCents, - 1 + -1 ), ComparisonCase( 56, Currency.Form.usDollarCents, 54, Currency.Form.usDollarCents, - -1 + 1 ), ).forEach { (amount1, form1, amount2, form2, expected) -> From bfa07fb75b69ea3c27e27911fc99e19d1ce9669a Mon Sep 17 00:00:00 2001 From: Taush Sampley Date: Thu, 12 Sep 2024 13:00:06 -0500 Subject: [PATCH 5/5] Account for loss of precision with larger denominator * convert both values to higher precision form --- .../src/commonMain/kotlin/business/Currency.kt | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/core/entities/src/commonMain/kotlin/business/Currency.kt b/core/entities/src/commonMain/kotlin/business/Currency.kt index c5b0588c..c420d589 100644 --- a/core/entities/src/commonMain/kotlin/business/Currency.kt +++ b/core/entities/src/commonMain/kotlin/business/Currency.kt @@ -92,8 +92,17 @@ internal class SimpleCurrency( override val form: Currency.Form, ): Currency { override fun compareTo(other: Currency): Int { - val otherValue = other.amount * form.centsPerUnit / other.form.centsPerUnit - return amount.compareTo(otherValue) + when { + form.centsPerUnit > other.form.centsPerUnit -> { + val thisValue = amount * form.centsPerUnit / other.form.centsPerUnit + return thisValue.compareTo(other.amount) + } + form.centsPerUnit < other.form.centsPerUnit -> { + val otherValue = other.amount * other.form.centsPerUnit / form.centsPerUnit + return amount.compareTo(otherValue) + } + else -> return amount.compareTo(other.amount) + } } override fun toString(): String {