From 83c38bad9e9535878b0bd5102a3d104fa8586e64 Mon Sep 17 00:00:00 2001 From: shamim-emon Date: Sun, 20 Oct 2024 13:55:26 +0600 Subject: [PATCH 1/5] Added Support For Large Number Formatting(Million, Billion) in FormatMoneyUseCase --- .../java/com/ivy/ui/FormatMoneyUseCase.kt | 24 +++++++++++++++---- .../java/com/ivy/ui/FormatMoneyUseCaseTest.kt | 24 +++++++++++++++++++ 2 files changed, 44 insertions(+), 4 deletions(-) diff --git a/shared/ui/core/src/main/java/com/ivy/ui/FormatMoneyUseCase.kt b/shared/ui/core/src/main/java/com/ivy/ui/FormatMoneyUseCase.kt index bc0114e044..076b4c625a 100644 --- a/shared/ui/core/src/main/java/com/ivy/ui/FormatMoneyUseCase.kt +++ b/shared/ui/core/src/main/java/com/ivy/ui/FormatMoneyUseCase.kt @@ -8,6 +8,9 @@ import java.text.DecimalFormat import java.text.DecimalFormatSymbols import javax.inject.Inject +const val MILLION = 1_000_000 +const val BILLION = 1_000_000_000 + class FormatMoneyUseCase @Inject constructor( private val features: Features, private val devicePreferences: DevicePreferences, @@ -19,11 +22,24 @@ class FormatMoneyUseCase @Inject constructor( private val withDecimalFormatter = DecimalFormat("###,###.00", DecimalFormatSymbols(locale)) suspend fun format(value: Double): String { - val showDecimalPoint = features.showDecimalNumber.isEnabled(context) + when (value >= MILLION) { + true -> { + val result = if (value >= BILLION) { + String.format(locale, "%.2fB", value / BILLION) + } else { + String.format(locale, "%.2fM", value / MILLION) + } + return result + } + + else -> { + val showDecimalPoint = features.showDecimalNumber.isEnabled(context) - return when (showDecimalPoint) { - true -> withDecimalFormatter.format(value) - false -> withoutDecimalFormatter.format(value) + return when (showDecimalPoint) { + true -> withDecimalFormatter.format(value) + false -> withoutDecimalFormatter.format(value) + } + } } } } \ No newline at end of file diff --git a/shared/ui/core/src/test/java/com/ivy/ui/FormatMoneyUseCaseTest.kt b/shared/ui/core/src/test/java/com/ivy/ui/FormatMoneyUseCaseTest.kt index 4a98251c3f..2ab16d219b 100644 --- a/shared/ui/core/src/test/java/com/ivy/ui/FormatMoneyUseCaseTest.kt +++ b/shared/ui/core/src/test/java/com/ivy/ui/FormatMoneyUseCaseTest.kt @@ -50,6 +50,30 @@ class FormatMoneyUseCaseTest { locale = Locale.GERMAN, expectedOutput = "1.000" ), + ENGLISH_MILLION( + amount = 1230000.10, + showDecimal = true, + locale = Locale.ENGLISH, + expectedOutput = "1.23M" + ), + ENGLISH_BILLION( + amount = 1233000000.10, + showDecimal = true, + locale = Locale.ENGLISH, + expectedOutput = "1.23B" + ), + GERMAN_MILLION( + amount = 1230000.10, + showDecimal = true, + locale = Locale.GERMAN, + expectedOutput = "1,23M" + ), + GERMAN_BILLION( + amount = 1233000000.10, + showDecimal = true, + locale = Locale.GERMAN, + expectedOutput = "1,23B" + ), } private lateinit var formatMoneyUseCase: FormatMoneyUseCase From 4cd16879bedeb9ffc145713438c66246d6529fc8 Mon Sep 17 00:00:00 2001 From: shamim-emon Date: Sun, 20 Oct 2024 17:00:14 +0600 Subject: [PATCH 2/5] Added Support For Large Number Formatting(Million, Billion,thousands) in FormatMoneyUseCase --- .../java/com/ivy/ui/FormatMoneyUseCase.kt | 14 +++--- .../java/com/ivy/ui/FormatMoneyUseCaseTest.kt | 44 +++++++++++++++---- 2 files changed, 44 insertions(+), 14 deletions(-) diff --git a/shared/ui/core/src/main/java/com/ivy/ui/FormatMoneyUseCase.kt b/shared/ui/core/src/main/java/com/ivy/ui/FormatMoneyUseCase.kt index 076b4c625a..5255a54843 100644 --- a/shared/ui/core/src/main/java/com/ivy/ui/FormatMoneyUseCase.kt +++ b/shared/ui/core/src/main/java/com/ivy/ui/FormatMoneyUseCase.kt @@ -7,9 +7,11 @@ import dagger.hilt.android.qualifiers.ApplicationContext import java.text.DecimalFormat import java.text.DecimalFormatSymbols import javax.inject.Inject +import kotlin.math.abs const val MILLION = 1_000_000 const val BILLION = 1_000_000_000 +const val HUNDREDOFTHOUSAND = 100000 class FormatMoneyUseCase @Inject constructor( private val features: Features, @@ -21,13 +23,15 @@ class FormatMoneyUseCase @Inject constructor( private val withoutDecimalFormatter = DecimalFormat("###,###", DecimalFormatSymbols(locale)) private val withDecimalFormatter = DecimalFormat("###,###.00", DecimalFormatSymbols(locale)) - suspend fun format(value: Double): String { - when (value >= MILLION) { + suspend fun format(value: Double, shortenAmount: Boolean): String { + when (abs(value) >= HUNDREDOFTHOUSAND && shortenAmount) { true -> { - val result = if (value >= BILLION) { - String.format(locale, "%.2fB", value / BILLION) + val result = if (abs(value) >= BILLION) { + String.format(locale, "%.2fb", value / BILLION) + } else if (abs(value) >= MILLION) { + String.format(locale, "%.2fm", value / MILLION) } else { - String.format(locale, "%.2fM", value / MILLION) + String.format(locale, "%.2fk", value / HUNDREDOFTHOUSAND) } return result } diff --git a/shared/ui/core/src/test/java/com/ivy/ui/FormatMoneyUseCaseTest.kt b/shared/ui/core/src/test/java/com/ivy/ui/FormatMoneyUseCaseTest.kt index 2ab16d219b..776548f345 100644 --- a/shared/ui/core/src/test/java/com/ivy/ui/FormatMoneyUseCaseTest.kt +++ b/shared/ui/core/src/test/java/com/ivy/ui/FormatMoneyUseCaseTest.kt @@ -23,56 +23,79 @@ class FormatMoneyUseCaseTest { enum class MoneyFormatterTestCase( val amount: Double, val showDecimal: Boolean, + val shortenAmount: Boolean, val locale: Locale, val expectedOutput: String ) { ENG_SHOW_DECIMAL( amount = 1000.12, showDecimal = true, + shortenAmount = false, locale = Locale.ENGLISH, expectedOutput = "1,000.12" ), ENG_HIDE_DECIMAL( amount = 1000.12, showDecimal = false, + shortenAmount = false, locale = Locale.ENGLISH, expectedOutput = "1,000" ), GERMAN_SHOW_DECIMAL( amount = 1000.12, showDecimal = true, + shortenAmount = false, locale = Locale.GERMAN, expectedOutput = "1.000,12" ), GERMAN_HIDE_DECIMAL( amount = 1000.12, showDecimal = false, + shortenAmount = false, locale = Locale.GERMAN, expectedOutput = "1.000" ), - ENGLISH_MILLION( + ENGLISH_100K_SHORT_AMT( + amount = 130000.10, + showDecimal = true, + shortenAmount = true, + locale = Locale.ENGLISH, + expectedOutput = "1.30k" + ), + ENGLISH_MILLION_SHORT_AMT( amount = 1230000.10, showDecimal = true, + shortenAmount = true, locale = Locale.ENGLISH, - expectedOutput = "1.23M" + expectedOutput = "1.23m" ), - ENGLISH_BILLION( + ENGLISH_BILLION_SHORT_AMT( amount = 1233000000.10, showDecimal = true, + shortenAmount = true, locale = Locale.ENGLISH, - expectedOutput = "1.23B" + expectedOutput = "1.23b" + ), + GERMAN_100K_SHORT_AMT( + amount = 130000.10, + showDecimal = true, + shortenAmount = true, + locale = Locale.GERMAN, + expectedOutput = "1,30k" ), - GERMAN_MILLION( + GERMAN_MILLION_SHORT_AMT( amount = 1230000.10, showDecimal = true, + shortenAmount = true, locale = Locale.GERMAN, - expectedOutput = "1,23M" + expectedOutput = "1,23m" ), - GERMAN_BILLION( + GERMAN_BILLION_SHORT_AMT( amount = 1233000000.10, showDecimal = true, + shortenAmount = true, locale = Locale.GERMAN, - expectedOutput = "1,23B" + expectedOutput = "1,23b" ), } @@ -89,7 +112,10 @@ class FormatMoneyUseCaseTest { formatMoneyUseCase = FormatMoneyUseCase(features, devicePreferences, context) // when - val result = formatMoneyUseCase.format(value = testCase.amount) + val result = formatMoneyUseCase.format( + value = testCase.amount, + shortenAmount = testCase.shortenAmount + ) // then result shouldBe testCase.expectedOutput From 668e5f9b85c96ded0a247a81f65e4d2d2c4588a9 Mon Sep 17 00:00:00 2001 From: shamim-emon Date: Sun, 20 Oct 2024 23:27:21 +0600 Subject: [PATCH 3/5] Added Support For Large Number Formatting(Million, Billion,thousands) in FormatMoneyUseCase - reviews resolved --- .../java/com/ivy/ui/FormatMoneyUseCase.kt | 6 ++-- .../java/com/ivy/ui/FormatMoneyUseCaseTest.kt | 28 +++++++++---------- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/shared/ui/core/src/main/java/com/ivy/ui/FormatMoneyUseCase.kt b/shared/ui/core/src/main/java/com/ivy/ui/FormatMoneyUseCase.kt index 5255a54843..21206cf2fd 100644 --- a/shared/ui/core/src/main/java/com/ivy/ui/FormatMoneyUseCase.kt +++ b/shared/ui/core/src/main/java/com/ivy/ui/FormatMoneyUseCase.kt @@ -11,7 +11,7 @@ import kotlin.math.abs const val MILLION = 1_000_000 const val BILLION = 1_000_000_000 -const val HUNDREDOFTHOUSAND = 100000 +const val THOUSAND = 1_000 class FormatMoneyUseCase @Inject constructor( private val features: Features, @@ -24,14 +24,14 @@ class FormatMoneyUseCase @Inject constructor( private val withDecimalFormatter = DecimalFormat("###,###.00", DecimalFormatSymbols(locale)) suspend fun format(value: Double, shortenAmount: Boolean): String { - when (abs(value) >= HUNDREDOFTHOUSAND && shortenAmount) { + when (abs(value) >= THOUSAND && shortenAmount) { true -> { val result = if (abs(value) >= BILLION) { String.format(locale, "%.2fb", value / BILLION) } else if (abs(value) >= MILLION) { String.format(locale, "%.2fm", value / MILLION) } else { - String.format(locale, "%.2fk", value / HUNDREDOFTHOUSAND) + String.format(locale, "%.2fk", value / THOUSAND) } return result } diff --git a/shared/ui/core/src/test/java/com/ivy/ui/FormatMoneyUseCaseTest.kt b/shared/ui/core/src/test/java/com/ivy/ui/FormatMoneyUseCaseTest.kt index 776548f345..5ac42e742c 100644 --- a/shared/ui/core/src/test/java/com/ivy/ui/FormatMoneyUseCaseTest.kt +++ b/shared/ui/core/src/test/java/com/ivy/ui/FormatMoneyUseCaseTest.kt @@ -28,70 +28,70 @@ class FormatMoneyUseCaseTest { val expectedOutput: String ) { ENG_SHOW_DECIMAL( - amount = 1000.12, + amount = 1_000.12, showDecimal = true, shortenAmount = false, locale = Locale.ENGLISH, expectedOutput = "1,000.12" ), ENG_HIDE_DECIMAL( - amount = 1000.12, + amount = 1_000.12, showDecimal = false, shortenAmount = false, locale = Locale.ENGLISH, expectedOutput = "1,000" ), GERMAN_SHOW_DECIMAL( - amount = 1000.12, + amount = 1_000.12, showDecimal = true, shortenAmount = false, locale = Locale.GERMAN, expectedOutput = "1.000,12" ), GERMAN_HIDE_DECIMAL( - amount = 1000.12, + amount = 1_000.12, showDecimal = false, shortenAmount = false, locale = Locale.GERMAN, expectedOutput = "1.000" ), - ENGLISH_100K_SHORT_AMT( - amount = 130000.10, + ENGLISH_1K_SHORT_AMT( + amount = 13_000.10, showDecimal = true, shortenAmount = true, locale = Locale.ENGLISH, - expectedOutput = "1.30k" + expectedOutput = "13.00k" ), ENGLISH_MILLION_SHORT_AMT( - amount = 1230000.10, + amount = 1_230_000.10, showDecimal = true, shortenAmount = true, locale = Locale.ENGLISH, expectedOutput = "1.23m" ), ENGLISH_BILLION_SHORT_AMT( - amount = 1233000000.10, + amount = 1_233_000_000.10, showDecimal = true, shortenAmount = true, locale = Locale.ENGLISH, expectedOutput = "1.23b" ), - GERMAN_100K_SHORT_AMT( - amount = 130000.10, + GERMAN_1K_SHORT_AMT( + amount = 13_000.10, showDecimal = true, shortenAmount = true, locale = Locale.GERMAN, - expectedOutput = "1,30k" + expectedOutput = "13,00k" ), GERMAN_MILLION_SHORT_AMT( - amount = 1230000.10, + amount = 1_230_000.10, showDecimal = true, shortenAmount = true, locale = Locale.GERMAN, expectedOutput = "1,23m" ), GERMAN_BILLION_SHORT_AMT( - amount = 1233000000.10, + amount = 1_233_000_000.10, showDecimal = true, shortenAmount = true, locale = Locale.GERMAN, From 7e779098d3cc5d13640604def7a49f402e41267d Mon Sep 17 00:00:00 2001 From: shamim-emon Date: Mon, 21 Oct 2024 05:38:27 +0600 Subject: [PATCH 4/5] Added Support For Large Number Formatting(Million, Billion,thousands) in FormatMoneyUseCase - refactored FormatMoneyUseCase + updated related unit tests --- .../java/com/ivy/ui/FormatMoneyUseCase.kt | 34 +++++++++---------- .../java/com/ivy/ui/FormatMoneyUseCaseTest.kt | 18 ++++++++-- 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/shared/ui/core/src/main/java/com/ivy/ui/FormatMoneyUseCase.kt b/shared/ui/core/src/main/java/com/ivy/ui/FormatMoneyUseCase.kt index 21206cf2fd..13cef9761a 100644 --- a/shared/ui/core/src/main/java/com/ivy/ui/FormatMoneyUseCase.kt +++ b/shared/ui/core/src/main/java/com/ivy/ui/FormatMoneyUseCase.kt @@ -9,9 +9,9 @@ import java.text.DecimalFormatSymbols import javax.inject.Inject import kotlin.math.abs +const val THOUSAND = 1_000 const val MILLION = 1_000_000 const val BILLION = 1_000_000_000 -const val THOUSAND = 1_000 class FormatMoneyUseCase @Inject constructor( private val features: Features, @@ -24,26 +24,24 @@ class FormatMoneyUseCase @Inject constructor( private val withDecimalFormatter = DecimalFormat("###,###.00", DecimalFormatSymbols(locale)) suspend fun format(value: Double, shortenAmount: Boolean): String { - when (abs(value) >= THOUSAND && shortenAmount) { - true -> { - val result = if (abs(value) >= BILLION) { - String.format(locale, "%.2fb", value / BILLION) - } else if (abs(value) >= MILLION) { - String.format(locale, "%.2fm", value / MILLION) - } else { - String.format(locale, "%.2fk", value / THOUSAND) - } - return result - } + val showDecimalPoint = features.showDecimalNumber.isEnabled(context) - else -> { - val showDecimalPoint = features.showDecimalNumber.isEnabled(context) + val formatter = when (showDecimalPoint) { + true -> withDecimalFormatter + false -> withoutDecimalFormatter + } - return when (showDecimalPoint) { - true -> withDecimalFormatter.format(value) - false -> withoutDecimalFormatter.format(value) - } + if (abs(value) >= THOUSAND && shortenAmount) { + val result = if (abs(value) >= BILLION) { + "${formatter.format(value / BILLION)}b" + } else if (abs(value) >= MILLION) { + "${formatter.format(value / MILLION)}m" + } else { + "${formatter.format(value / THOUSAND)}k" } + return result + } else { + return formatter.format(value) } } } \ No newline at end of file diff --git a/shared/ui/core/src/test/java/com/ivy/ui/FormatMoneyUseCaseTest.kt b/shared/ui/core/src/test/java/com/ivy/ui/FormatMoneyUseCaseTest.kt index 5ac42e742c..3cea2f22a3 100644 --- a/shared/ui/core/src/test/java/com/ivy/ui/FormatMoneyUseCaseTest.kt +++ b/shared/ui/core/src/test/java/com/ivy/ui/FormatMoneyUseCaseTest.kt @@ -56,6 +56,13 @@ class FormatMoneyUseCaseTest { expectedOutput = "1.000" ), ENGLISH_1K_SHORT_AMT( + amount = 13_000.10, + showDecimal = false, + shortenAmount = true, + locale = Locale.ENGLISH, + expectedOutput = "13k" + ), + ENGLISH_1K_SHORT_AMT_SHOW_DECIMAL( amount = 13_000.10, showDecimal = true, shortenAmount = true, @@ -63,7 +70,7 @@ class FormatMoneyUseCaseTest { expectedOutput = "13.00k" ), ENGLISH_MILLION_SHORT_AMT( - amount = 1_230_000.10, + amount = 1_233_500.10, showDecimal = true, shortenAmount = true, locale = Locale.ENGLISH, @@ -77,6 +84,13 @@ class FormatMoneyUseCaseTest { expectedOutput = "1.23b" ), GERMAN_1K_SHORT_AMT( + amount = 13_000.10, + showDecimal = false, + shortenAmount = true, + locale = Locale.GERMAN, + expectedOutput = "13k" + ), + GERMAN_1K_SHORT_AMT_SHOW_DECIMAL( amount = 13_000.10, showDecimal = true, shortenAmount = true, @@ -84,7 +98,7 @@ class FormatMoneyUseCaseTest { expectedOutput = "13,00k" ), GERMAN_MILLION_SHORT_AMT( - amount = 1_230_000.10, + amount = 1_233_500.10, showDecimal = true, shortenAmount = true, locale = Locale.GERMAN, From 0469876f19438c455c8ca9f05a542cf3b299ea49 Mon Sep 17 00:00:00 2001 From: shamim-emon Date: Mon, 21 Oct 2024 15:04:16 +0600 Subject: [PATCH 5/5] Added Support For Large Number Formatting(Million, Billion,thousands) in FormatMoneyUseCase - added shortenAmountFormatter --- .../java/com/ivy/ui/FormatMoneyUseCase.kt | 20 +++++++++---------- .../java/com/ivy/ui/FormatMoneyUseCaseTest.kt | 18 ++--------------- 2 files changed, 12 insertions(+), 26 deletions(-) diff --git a/shared/ui/core/src/main/java/com/ivy/ui/FormatMoneyUseCase.kt b/shared/ui/core/src/main/java/com/ivy/ui/FormatMoneyUseCase.kt index 13cef9761a..d1aed35b19 100644 --- a/shared/ui/core/src/main/java/com/ivy/ui/FormatMoneyUseCase.kt +++ b/shared/ui/core/src/main/java/com/ivy/ui/FormatMoneyUseCase.kt @@ -22,25 +22,25 @@ class FormatMoneyUseCase @Inject constructor( private val locale = devicePreferences.locale() private val withoutDecimalFormatter = DecimalFormat("###,###", DecimalFormatSymbols(locale)) private val withDecimalFormatter = DecimalFormat("###,###.00", DecimalFormatSymbols(locale)) + private val shortenAmountFormatter = DecimalFormat("###,###.##", DecimalFormatSymbols(locale)) suspend fun format(value: Double, shortenAmount: Boolean): String { - val showDecimalPoint = features.showDecimalNumber.isEnabled(context) - - val formatter = when (showDecimalPoint) { - true -> withDecimalFormatter - false -> withoutDecimalFormatter - } - if (abs(value) >= THOUSAND && shortenAmount) { val result = if (abs(value) >= BILLION) { - "${formatter.format(value / BILLION)}b" + "${shortenAmountFormatter.format(value / BILLION)}b" } else if (abs(value) >= MILLION) { - "${formatter.format(value / MILLION)}m" + "${shortenAmountFormatter.format(value / MILLION)}m" } else { - "${formatter.format(value / THOUSAND)}k" + "${shortenAmountFormatter.format(value / THOUSAND)}k" } return result } else { + val showDecimalPoint = features.showDecimalNumber.isEnabled(context) + + val formatter = when (showDecimalPoint) { + true -> withDecimalFormatter + false -> withoutDecimalFormatter + } return formatter.format(value) } } diff --git a/shared/ui/core/src/test/java/com/ivy/ui/FormatMoneyUseCaseTest.kt b/shared/ui/core/src/test/java/com/ivy/ui/FormatMoneyUseCaseTest.kt index 3cea2f22a3..a477fcbda6 100644 --- a/shared/ui/core/src/test/java/com/ivy/ui/FormatMoneyUseCaseTest.kt +++ b/shared/ui/core/src/test/java/com/ivy/ui/FormatMoneyUseCaseTest.kt @@ -56,18 +56,11 @@ class FormatMoneyUseCaseTest { expectedOutput = "1.000" ), ENGLISH_1K_SHORT_AMT( - amount = 13_000.10, - showDecimal = false, - shortenAmount = true, - locale = Locale.ENGLISH, - expectedOutput = "13k" - ), - ENGLISH_1K_SHORT_AMT_SHOW_DECIMAL( amount = 13_000.10, showDecimal = true, shortenAmount = true, locale = Locale.ENGLISH, - expectedOutput = "13.00k" + expectedOutput = "13k" ), ENGLISH_MILLION_SHORT_AMT( amount = 1_233_500.10, @@ -84,18 +77,11 @@ class FormatMoneyUseCaseTest { expectedOutput = "1.23b" ), GERMAN_1K_SHORT_AMT( - amount = 13_000.10, - showDecimal = false, - shortenAmount = true, - locale = Locale.GERMAN, - expectedOutput = "13k" - ), - GERMAN_1K_SHORT_AMT_SHOW_DECIMAL( amount = 13_000.10, showDecimal = true, shortenAmount = true, locale = Locale.GERMAN, - expectedOutput = "13,00k" + expectedOutput = "13k" ), GERMAN_MILLION_SHORT_AMT( amount = 1_233_500.10,