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

[Feature] Added Decimal Formatting Capability #3568

Merged
merged 4 commits into from
Sep 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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>
}
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)
}
}
}
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)
ILIYANGERMANOV marked this conversation as resolved.
Show resolved Hide resolved
class FormatMoneyUseCaseTest {
ILIYANGERMANOV marked this conversation as resolved.
Show resolved Hide resolved

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
}
}