Skip to content
This repository has been archived by the owner on Nov 5, 2024. It is now read-only.

Commit

Permalink
Updated FormatMoneyUseCase
Browse files Browse the repository at this point in the history
  • Loading branch information
shamim-emon committed Nov 1, 2024
1 parent 0e112f2 commit 9d56c95
Show file tree
Hide file tree
Showing 24 changed files with 126 additions and 29 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ import com.ivy.navigation.navigation
import com.ivy.navigation.screenScopedViewModel
import com.ivy.ui.R
import com.ivy.wallet.domain.data.CustomExchangeRateState
import com.ivy.wallet.domain.data.IvyCurrency
import com.ivy.legacy.domain.data.IvyCurrency
import com.ivy.wallet.domain.deprecated.logic.model.CreateAccountData
import com.ivy.wallet.domain.deprecated.logic.model.CreateCategoryData
import com.ivy.wallet.ui.edit.core.Category
Expand Down
2 changes: 1 addition & 1 deletion screen/home/src/main/java/com/ivy/home/HomeTab.kt
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ import com.ivy.navigation.IvyPreview
import com.ivy.navigation.screenScopedViewModel
import com.ivy.ui.R
import com.ivy.ui.rememberScrollPositionListState
import com.ivy.wallet.domain.data.IvyCurrency
import com.ivy.legacy.domain.data.IvyCurrency
import com.ivy.wallet.domain.pure.data.IncomeExpensePair
import com.ivy.wallet.ui.theme.modal.BufferModal
import com.ivy.wallet.ui.theme.modal.BufferModalData
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import com.ivy.legacy.datamodel.Account
import com.ivy.legacy.datamodel.temp.toLegacyDomain
import com.ivy.legacy.datamodel.toEntity
import com.ivy.legacy.utils.toLowerCaseLocal
import com.ivy.wallet.domain.data.IvyCurrency
import com.ivy.legacy.domain.data.IvyCurrency
import com.ivy.wallet.domain.pure.util.nextOrderNum
import com.ivy.wallet.ui.theme.Green
import com.ivy.wallet.ui.theme.IvyDark
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ import com.ivy.navigation.TransactionsScreen
import com.ivy.navigation.navigation
import com.ivy.ui.R
import com.ivy.ui.time.TimeFormatter
import com.ivy.wallet.domain.data.IvyCurrency
import com.ivy.legacy.domain.data.IvyCurrency
import com.ivy.wallet.ui.theme.Gradient
import com.ivy.wallet.ui.theme.Gray
import com.ivy.wallet.ui.theme.MediumBlack
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package com.ivy.onboarding
import androidx.compose.runtime.Immutable
import com.ivy.data.model.Category
import com.ivy.legacy.data.model.AccountBalance
import com.ivy.wallet.domain.data.IvyCurrency
import com.ivy.legacy.domain.data.IvyCurrency
import com.ivy.wallet.domain.deprecated.logic.model.CreateAccountData
import com.ivy.wallet.domain.deprecated.logic.model.CreateCategoryData
import kotlinx.collections.immutable.ImmutableList
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ package com.ivy.onboarding

import com.ivy.data.model.Category
import com.ivy.legacy.datamodel.Account
import com.ivy.wallet.domain.data.IvyCurrency
import com.ivy.legacy.domain.data.IvyCurrency
import com.ivy.wallet.domain.deprecated.logic.model.CreateAccountData
import com.ivy.wallet.domain.deprecated.logic.model.CreateCategoryData

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import com.ivy.onboarding.steps.OnboardingSetCurrency
import com.ivy.onboarding.steps.OnboardingSplashLogin
import com.ivy.onboarding.steps.OnboardingType
import com.ivy.onboarding.viewmodel.OnboardingViewModel
import com.ivy.wallet.domain.data.IvyCurrency
import com.ivy.legacy.domain.data.IvyCurrency
import com.ivy.wallet.domain.deprecated.logic.model.CreateAccountData
import com.ivy.wallet.domain.deprecated.logic.model.CreateCategoryData
import kotlinx.collections.immutable.ImmutableList
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import com.ivy.legacy.IvyWalletPreview
import com.ivy.legacy.utils.setStatusBarDarkTextCompat
import com.ivy.navigation.navigation
import com.ivy.ui.R
import com.ivy.wallet.domain.data.IvyCurrency
import com.ivy.legacy.domain.data.IvyCurrency
import com.ivy.wallet.ui.theme.GradientIvy
import com.ivy.wallet.ui.theme.White
import com.ivy.wallet.ui.theme.components.BackButton
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import com.ivy.navigation.MainScreen
import com.ivy.navigation.Navigation
import com.ivy.navigation.OnboardingScreen
import com.ivy.onboarding.OnboardingState
import com.ivy.wallet.domain.data.IvyCurrency
import com.ivy.legacy.domain.data.IvyCurrency
import com.ivy.wallet.domain.deprecated.logic.PreloadDataLogic
import com.ivy.wallet.domain.deprecated.logic.model.CreateAccountData
import com.ivy.wallet.domain.deprecated.logic.model.CreateCategoryData
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import com.ivy.onboarding.OnboardingDetailState
import com.ivy.onboarding.OnboardingEvent
import com.ivy.onboarding.OnboardingState
import com.ivy.wallet.domain.action.account.AccountsAct
import com.ivy.wallet.domain.data.IvyCurrency
import com.ivy.legacy.domain.data.IvyCurrency
import com.ivy.wallet.domain.deprecated.logic.CategoryCreator
import com.ivy.wallet.domain.deprecated.logic.PreloadDataLogic
import com.ivy.wallet.domain.deprecated.logic.WalletAccountLogic
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ import com.ivy.navigation.ReleasesScreen
import com.ivy.navigation.navigation
import com.ivy.navigation.screenScopedViewModel
import com.ivy.ui.R
import com.ivy.wallet.domain.data.IvyCurrency
import com.ivy.legacy.domain.data.IvyCurrency
import com.ivy.wallet.ui.theme.Blue
import com.ivy.wallet.ui.theme.Gradient
import com.ivy.wallet.ui.theme.GradientGreen
Expand Down
65 changes: 59 additions & 6 deletions shared/ui/core/src/main/java/com/ivy/ui/FormatMoneyUseCase.kt
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,15 @@ const val THOUSAND = 1_000
const val MILLION = 1_000_000
const val BILLION = 1_000_000_000

/**
* A use case class responsible for formatting currency and cryptocurrency values based on user preferences.
* It supports regular currency formatting with or without decimal places, as well as shortened formats
* (e.g., "1k", "1m"). For cryptocurrency, it formats up to 9 decimal places and removes unnecessary trailing zeros.
*
* @property features Provides feature toggles to customize app behavior.
* @property devicePreferences Manages user-specific preferences for locale and other device settings.
* @property context Application context, used for feature check and resource access.
*/
class FormatMoneyUseCase @Inject constructor(
private val features: Features,
private val devicePreferences: DevicePreferences,
Expand All @@ -23,25 +32,69 @@ class FormatMoneyUseCase @Inject constructor(
private val withoutDecimalFormatter = DecimalFormat("###,###", DecimalFormatSymbols(locale))
private val withDecimalFormatter = DecimalFormat("###,###.00", DecimalFormatSymbols(locale))
private val shortenAmountFormatter = DecimalFormat("###,###.##", DecimalFormatSymbols(locale))
private val cryptoFormatter =
DecimalFormat("###,###,##0.${"0".repeat(9)}", DecimalFormatSymbols(locale))

suspend fun format(value: Double, shortenAmount: Boolean): String {
if (abs(value) >= THOUSAND && shortenAmount) {
val result = if (abs(value) >= BILLION) {
/**
* Formats a currency or cryptocurrency amount based on the input parameters.
*
* @param value The numeric value to format.
* @param shortenAmount Flag to indicate if the amount should be shortened (e.g., "1k" for 1,000).
* @param isCrypto Flag to indicate if the value is a cryptocurrency, enabling up to 9 decimal places.
* @return The formatted string representation of the value.
*/
suspend fun format(value: Double, shortenAmount: Boolean, isCrypto: Boolean = false): String {
val result = if (isCrypto) {
formatCrypto(value)
} else if (abs(value) >= THOUSAND && shortenAmount) {
if (abs(value) >= BILLION) {
"${shortenAmountFormatter.format(value / BILLION)}b"
} else if (abs(value) >= MILLION) {
"${shortenAmountFormatter.format(value / MILLION)}m"
} else {
"${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)
formatter.format(value)
}

return result
}

/**
* Formats a cryptocurrency value with up to 9 decimal places, removing unnecessary trailing zeros.
*
* @param value The cryptocurrency value to format.
* @return The formatted cryptocurrency value as a string.
*/
private fun formatCrypto(value: Double): String {
val result = cryptoFormatter.format(value)
return when {
result.lastOrNull() == localDecimalSeparator().firstOrNull() -> {
val newResult = result.dropLast(1)
newResult.ifEmpty { "0" }
}

result.isEmpty() -> {
"0"
}

else -> result
}
}

/**
* Retrieves the local decimal separator based on the user's locale.
*
* @return The decimal separator as a string.
*/
private fun localDecimalSeparator(): String {
return DecimalFormatSymbols(locale).decimalSeparator.toString()
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,79 +24,122 @@ class FormatMoneyUseCaseTest {
val amount: Double,
val showDecimal: Boolean,
val shortenAmount: Boolean,
val isCrypto: Boolean,
val locale: Locale,
val expectedOutput: String
) {
ENG_SHOW_DECIMAL(
amount = 1_000.12,
showDecimal = true,
shortenAmount = false,
isCrypto = false,
locale = Locale.ENGLISH,
expectedOutput = "1,000.12"
),
ENG_HIDE_DECIMAL(
amount = 1_000.12,
showDecimal = false,
shortenAmount = false,
isCrypto = false,
locale = Locale.ENGLISH,
expectedOutput = "1,000"
),
GERMAN_SHOW_DECIMAL(
amount = 1_000.12,
showDecimal = true,
shortenAmount = false,
isCrypto = false,
locale = Locale.GERMAN,
expectedOutput = "1.000,12"
),
GERMAN_HIDE_DECIMAL(
amount = 1_000.12,
showDecimal = false,
shortenAmount = false,
isCrypto = false,
locale = Locale.GERMAN,
expectedOutput = "1.000"
),
ENGLISH_1K_SHORT_AMT(
amount = 13_000.10,
showDecimal = true,
shortenAmount = true,
isCrypto = false,
locale = Locale.ENGLISH,
expectedOutput = "13k"
),
ENGLISH_MILLION_SHORT_AMT(
amount = 1_233_500.10,
showDecimal = true,
shortenAmount = true,
isCrypto = false,
locale = Locale.ENGLISH,
expectedOutput = "1.23m"
),
ENGLISH_BILLION_SHORT_AMT(
amount = 1_233_000_000.10,
showDecimal = true,
shortenAmount = true,
isCrypto = false,
locale = Locale.ENGLISH,
expectedOutput = "1.23b"
),
GERMAN_1K_SHORT_AMT(
amount = 13_000.10,
showDecimal = true,
shortenAmount = true,
isCrypto = false,
locale = Locale.GERMAN,
expectedOutput = "13k"
),
GERMAN_MILLION_SHORT_AMT(
amount = 1_233_500.10,
showDecimal = true,
shortenAmount = true,
isCrypto = false,
locale = Locale.GERMAN,
expectedOutput = "1,23m"
),
GERMAN_BILLION_SHORT_AMT(
amount = 1_233_000_000.10,
showDecimal = true,
shortenAmount = true,
isCrypto = false,
locale = Locale.GERMAN,
expectedOutput = "1,23b"
),
ENG_SHOW_DECIMAL_CRYPTO(
amount = 123_456.0,
showDecimal = true,
shortenAmount = false,
isCrypto = true,
locale = Locale.ENGLISH,
expectedOutput = "123,456.000000000"
),
ENG_HIDE_DECIMAL_CRYPTO(
amount = 123_456.0,
showDecimal = false,
shortenAmount = false,
isCrypto = true,
locale = Locale.ENGLISH,
expectedOutput = "123,456.000000000"
),
GERMAN_SHOW_DECIMAL_CRYPTO(
amount = 123_456.0,
showDecimal = true,
shortenAmount = false,
isCrypto = true,
locale = Locale.GERMAN,
expectedOutput = "123.456,000000000"
),
GERMAN_HIDE_DECIMAL_CRYPTO(
amount = 123_456.0,
showDecimal = false,
shortenAmount = false,
isCrypto = true,
locale = Locale.GERMAN,
expectedOutput = "123.456,000000000"
),
}

private lateinit var formatMoneyUseCase: FormatMoneyUseCase
Expand All @@ -114,7 +157,8 @@ class FormatMoneyUseCaseTest {
// when
val result = formatMoneyUseCase.format(
value = testCase.amount,
shortenAmount = testCase.shortenAmount
shortenAmount = testCase.shortenAmount,
isCrypto = testCase.isCrypto
)

// then
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.ivy.wallet.domain.data
package com.ivy.legacy.domain.data

import android.icu.util.Currency
import androidx.compose.runtime.Immutable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import com.ivy.legacy.datamodel.toEntity
import com.ivy.legacy.utils.convertLocalToUTC
import com.ivy.legacy.utils.timeNowUTC
import com.ivy.legacy.utils.toLowerCaseLocal
import com.ivy.wallet.domain.data.IvyCurrency
import com.ivy.legacy.domain.data.IvyCurrency
import com.ivy.wallet.domain.deprecated.logic.csv.model.RowMapping
import com.ivy.wallet.domain.pure.util.nextOrderNum
import com.opencsv.CSVReaderBuilder
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ import com.ivy.legacy.utils.keyboardOnlyWindowInsets
import com.ivy.legacy.utils.onScreenStart
import com.ivy.legacy.utils.toLowerCaseLocal
import com.ivy.ui.R
import com.ivy.wallet.domain.data.IvyCurrency
import com.ivy.legacy.domain.data.IvyCurrency
import com.ivy.wallet.ui.theme.GradientGreen
import com.ivy.wallet.ui.theme.GradientIvy
import com.ivy.wallet.ui.theme.Ivy
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import com.ivy.design.l0_system.style
import com.ivy.legacy.IvyWalletComponentPreview
import com.ivy.legacy.utils.format
import com.ivy.ui.R
import com.ivy.wallet.domain.data.IvyCurrency
import com.ivy.legacy.domain.data.IvyCurrency
import com.ivy.wallet.ui.theme.Orange

@Deprecated("Old design system. Use `:ivy-design` and Material3")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import com.ivy.design.l0_system.UI
import com.ivy.design.l0_system.style
import com.ivy.legacy.IvyWalletPreview
import com.ivy.ui.R
import com.ivy.wallet.domain.data.IvyCurrency
import com.ivy.legacy.domain.data.IvyCurrency
import com.ivy.wallet.ui.theme.Gray
import com.ivy.wallet.ui.theme.components.CurrencyPicker
import java.util.UUID
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ import com.ivy.legacy.utils.selectEndTextFieldValue
import com.ivy.design.utils.thenIf
import com.ivy.legacy.legacy.ui.theme.modal.ModalNameInput
import com.ivy.ui.R
import com.ivy.wallet.domain.data.IvyCurrency
import com.ivy.legacy.domain.data.IvyCurrency
import com.ivy.wallet.domain.deprecated.logic.model.CreateAccountData
import com.ivy.wallet.domain.deprecated.logic.model.CreateLoanData
import com.ivy.wallet.ui.theme.GradientIvy
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ import com.ivy.legacy.utils.selectEndTextFieldValue
import com.ivy.legacy.utils.toLowerCaseLocal
import com.ivy.legacy.utils.toUpperCaseLocal
import com.ivy.ui.R
import com.ivy.wallet.domain.data.IvyCurrency
import com.ivy.legacy.domain.data.IvyCurrency
import com.ivy.wallet.domain.deprecated.logic.model.CreateAccountData
import com.ivy.wallet.ui.theme.Gray
import com.ivy.wallet.ui.theme.Ivy
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import com.ivy.design.l0_system.style
import com.ivy.legacy.utils.drawColoredShadow
import com.ivy.legacy.utils.format
import com.ivy.ui.R
import com.ivy.wallet.domain.data.IvyCurrency
import com.ivy.legacy.domain.data.IvyCurrency
import com.ivy.wallet.ui.theme.Gradient
import com.ivy.wallet.ui.theme.Green
import com.ivy.wallet.ui.theme.MediumBlack
Expand Down
Loading

0 comments on commit 9d56c95

Please sign in to comment.