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

Commit

Permalink
[Feature] Added Decimal Formatting Capability (#3568)
Browse files Browse the repository at this point in the history
* Under dev

* Under dev

* Decimal number capability added

* Decimal number capability added : Reviews resolved
  • Loading branch information
shamim-emon authored Sep 30, 2024
1 parent da86ec6 commit 7e8cc57
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ interface Features {
val showTitleSuggestions: BoolFeature
val showCategorySearchBar: BoolFeature
val hideTotalBalance: BoolFeature
val showDecimalNumber: BoolFeature

val allFeatures: List<BoolFeature>
}
16 changes: 14 additions & 2 deletions shared/domain/src/main/java/com/ivy/domain/features/IvyFeatures.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class IvyFeatures @Inject constructor() : Features {

override val sortCategoriesAlphabetically = BoolFeature(
key = "sort_categories_alphabetically",
group = FeatureGroup.Other,
group = FeatureGroup.Category,
name = "Sort Categories Alphabetically",
description = "Sort income and expenses" +
" categories alphabetically"
Expand Down Expand Up @@ -52,13 +52,25 @@ class IvyFeatures @Inject constructor() : Features {
defaultValue = false
)

override val showDecimalNumber = BoolFeature(
key = "show_decimal_number",
group = FeatureGroup.Other,
name = "Show Decimal Number",
description = "Whether to show the decimal part in amounts",
defaultValue = true
)

override val allFeatures: List<BoolFeature>
get() = listOf(
sortCategoriesAlphabetically,
compactAccountsMode,
compactCategoriesMode,
showTitleSuggestions,
showCategorySearchBar,
hideTotalBalance
hideTotalBalance,
/* will be uncommented when this functionality
* will be available across the application in up-coming PRs
showDecimalNumber
*/
)
}
29 changes: 29 additions & 0 deletions shared/ui/core/src/main/java/com/ivy/ui/FormatMoneyUseCase.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package com.ivy.ui

import android.content.Context
import com.ivy.domain.features.Features
import com.ivy.ui.time.DevicePreferences
import dagger.hilt.android.qualifiers.ApplicationContext
import java.text.DecimalFormat
import java.text.DecimalFormatSymbols
import javax.inject.Inject

class FormatMoneyUseCase @Inject constructor(
private val features: Features,
private val devicePreferences: DevicePreferences,
@ApplicationContext private val context: Context
) {

private val locale = devicePreferences.locale()
private val withoutDecimalFormatter = DecimalFormat("###,###", DecimalFormatSymbols(locale))
private val withDecimalFormatter = DecimalFormat("###,###.00", DecimalFormatSymbols(locale))

suspend fun format(value: Double): String {
val showDecimalPoint = features.showDecimalNumber.isEnabled(context)

return when (showDecimalPoint) {
true -> withDecimalFormatter.format(value)
false -> withoutDecimalFormatter.format(value)
}
}
}
73 changes: 73 additions & 0 deletions shared/ui/core/src/test/java/com/ivy/ui/FormatMoneyUseCaseTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
package com.ivy.ui

import android.content.Context
import com.google.testing.junit.testparameterinjector.TestParameter
import com.google.testing.junit.testparameterinjector.TestParameterInjector
import com.ivy.domain.features.Features
import com.ivy.ui.time.DevicePreferences
import io.kotest.common.runBlocking
import io.kotest.matchers.shouldBe
import io.mockk.coEvery
import io.mockk.every
import io.mockk.mockk
import org.junit.Test
import org.junit.runner.RunWith
import java.util.Locale

@RunWith(TestParameterInjector::class)
class FormatMoneyUseCaseTest {

private val features = mockk<Features>()
private val devicePreferences = mockk<DevicePreferences>()

enum class MoneyFormatterTestCase(
val amount: Double,
val showDecimal: Boolean,
val locale: Locale,
val expectedOutput: String
) {
ENG_SHOW_DECIMAL(
amount = 1000.12,
showDecimal = true,
locale = Locale.ENGLISH,
expectedOutput = "1,000.12"
),
ENG_HIDE_DECIMAL(
amount = 1000.12,
showDecimal = false,
locale = Locale.ENGLISH,
expectedOutput = "1,000"
),
GERMAN_SHOW_DECIMAL(
amount = 1000.12,
showDecimal = true,
locale = Locale.GERMAN,
expectedOutput = "1.000,12"
),
GERMAN_HIDE_DECIMAL(
amount = 1000.12,
showDecimal = false,
locale = Locale.GERMAN,
expectedOutput = "1.000"
),
}

private lateinit var formatMoneyUseCase: FormatMoneyUseCase

@Test
fun `validate decimal formatting`(
@TestParameter testCase: MoneyFormatterTestCase
): Unit = runBlocking {
// given
val context = mockk<Context>()
every { features.showDecimalNumber } returns mockk { coEvery { isEnabled(any()) } returns testCase.showDecimal }
every { devicePreferences.locale() } returns testCase.locale
formatMoneyUseCase = FormatMoneyUseCase(features, devicePreferences, context)

// when
val result = formatMoneyUseCase.format(value = testCase.amount)

// then
result shouldBe testCase.expectedOutput
}
}

0 comments on commit 7e8cc57

Please sign in to comment.