From b265fadec3a39606a9aeb1f869bab7fd671db0f6 Mon Sep 17 00:00:00 2001 From: Sylvia van Os Date: Tue, 23 Feb 2021 18:48:49 +0100 Subject: [PATCH] Improve currency parsing logic --- CHANGELOG.md | 6 ++ app/build.gradle | 4 +- .../card_locker/LoyaltyCardEditActivity.java | 2 +- .../main/java/protect/card_locker/Utils.java | 16 +++- .../java/protect/card_locker/UtilsTest.java | 85 +++++++++++++++---- 5 files changed, 94 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4a9af34e5..94740dec9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## v1.9.1 (2021-02-23) + +Changes: + +- Improve balance parsing logic + ## v1.9 (2021-02-22) Changes: diff --git a/app/build.gradle b/app/build.gradle index 2a4bdfaac..3340fda43 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -18,8 +18,8 @@ android { applicationId "me.hackerchick.catima" minSdkVersion 19 targetSdkVersion 29 - versionCode 59 - versionName "1.9" + versionCode 60 + versionName "1.9.1" vectorDrawables.useSupportLibrary true } diff --git a/app/src/main/java/protect/card_locker/LoyaltyCardEditActivity.java b/app/src/main/java/protect/card_locker/LoyaltyCardEditActivity.java index d5b2fc853..33ae5fcc0 100644 --- a/app/src/main/java/protect/card_locker/LoyaltyCardEditActivity.java +++ b/app/src/main/java/protect/card_locker/LoyaltyCardEditActivity.java @@ -214,7 +214,7 @@ public class LoyaltyCardEditActivity extends AppCompatActivity hasChanged = true; try { - BigDecimal balance = Utils.parseCurrency(s.toString()); + BigDecimal balance = Utils.parseCurrency(s.toString(), Utils.currencyHasDecimals((Currency) balanceCurrencyField.getTag())); validBalance = true; balanceField.setTag(balance); diff --git a/app/src/main/java/protect/card_locker/Utils.java b/app/src/main/java/protect/card_locker/Utils.java index 468555e8c..c045ff900 100644 --- a/app/src/main/java/protect/card_locker/Utils.java +++ b/app/src/main/java/protect/card_locker/Utils.java @@ -112,7 +112,21 @@ public class Utils { return numberFormat.format(value); } - static public BigDecimal parseCurrency(String value) throws NumberFormatException { + static public Boolean currencyHasDecimals(Currency currency) { + if (currency == null) { + return false; + } + + return currency.getDefaultFractionDigits() != 0; + } + + static public BigDecimal parseCurrency(String value, Boolean hasDecimals) throws NumberFormatException { + // If there are no decimals expected, remove all separators before parsing + if (!hasDecimals) { + value = value.replaceAll("\\.", "").replaceAll(",", ""); + return new BigDecimal(value); + } + // There are many ways users can write a currency, so we fix it up a bit // 1. Replace all commas with dots value = value.replace(',', '.'); diff --git a/app/src/test/java/protect/card_locker/UtilsTest.java b/app/src/test/java/protect/card_locker/UtilsTest.java index d38b766e4..f4df8773d 100644 --- a/app/src/test/java/protect/card_locker/UtilsTest.java +++ b/app/src/test/java/protect/card_locker/UtilsTest.java @@ -5,6 +5,10 @@ import org.junit.Test; import org.junit.runner.RunWith; import org.robolectric.RobolectricTestRunner; import org.robolectric.annotation.Config; +import org.robolectric.util.Util; + +import java.math.BigDecimal; +import java.util.Currency; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThrows; @@ -16,21 +20,72 @@ public class UtilsTest @Test public void parseBalances() { - assertEquals("1000.00", Utils.parseCurrency("1.000.00").toPlainString()); - assertEquals("1000.50", Utils.parseCurrency("1.000.50").toPlainString()); - assertEquals("1000.50", Utils.parseCurrency("1.000,50").toPlainString()); - assertEquals("1000.50", Utils.parseCurrency("1,000,50").toPlainString()); - assertEquals("1000.50", Utils.parseCurrency("1,000.50").toPlainString()); - assertEquals("1000", Utils.parseCurrency("1000").toPlainString()); - assertEquals("995", Utils.parseCurrency("995").toPlainString()); - assertEquals("9.95", Utils.parseCurrency("9.95").toPlainString()); - assertEquals("9.95", Utils.parseCurrency("9,95").toPlainString()); + assertEquals("1", Utils.parseCurrency("1", false).toPlainString()); - assertThrows(NumberFormatException.class, () -> Utils.parseCurrency("")); - assertThrows(NumberFormatException.class, () -> Utils.parseCurrency(".")); - assertThrows(NumberFormatException.class, () -> Utils.parseCurrency(",")); - assertThrows(NumberFormatException.class, () -> Utils.parseCurrency(".,")); - assertThrows(NumberFormatException.class, () -> Utils.parseCurrency("a")); - assertThrows(NumberFormatException.class, () -> Utils.parseCurrency("......................")); + assertEquals("1", Utils.parseCurrency("1", true).toPlainString()); + assertEquals("1.00", Utils.parseCurrency("1.00", true).toPlainString()); + assertEquals("1.00", Utils.parseCurrency("1,00", true).toPlainString()); + + assertEquals("25", Utils.parseCurrency("2.5", false).toPlainString()); + assertEquals("25", Utils.parseCurrency("2,5", false).toPlainString()); + assertEquals("205", Utils.parseCurrency("2.05", false).toPlainString()); + assertEquals("205", Utils.parseCurrency("2,05", false).toPlainString()); + + assertEquals("2.5", Utils.parseCurrency("2.5", true).toPlainString()); + assertEquals("2.5", Utils.parseCurrency("2,5", true).toPlainString()); + assertEquals("2.05", Utils.parseCurrency("2.05", true).toPlainString()); + assertEquals("2.05", Utils.parseCurrency("2,05", true).toPlainString()); + assertEquals("2.50", Utils.parseCurrency("2.50", true).toPlainString()); + assertEquals("2.50", Utils.parseCurrency("2,50", true).toPlainString()); + + assertEquals("995", Utils.parseCurrency("9.95", false).toPlainString()); + assertEquals("995", Utils.parseCurrency("9,95", false).toPlainString()); + + assertEquals("9.95", Utils.parseCurrency("9.95", true).toPlainString()); + assertEquals("9.95", Utils.parseCurrency("9,95", true).toPlainString()); + + assertEquals("1234", Utils.parseCurrency("1234", false).toPlainString()); + assertEquals("1234", Utils.parseCurrency("1.234", false).toPlainString()); + assertEquals("1234", Utils.parseCurrency("1,234", false).toPlainString()); + + assertEquals("1234", Utils.parseCurrency("1234", true).toPlainString()); + assertEquals("1234.00", Utils.parseCurrency("1234.00", true).toPlainString()); + assertEquals("1234.00", Utils.parseCurrency("1.234.00", true).toPlainString()); + assertEquals("1234.00", Utils.parseCurrency("1.234,00", true).toPlainString()); + assertEquals("1234.00", Utils.parseCurrency("1,234.00", true).toPlainString()); + assertEquals("1234.00", Utils.parseCurrency("1,234,00", true).toPlainString()); + } + + @Test + public void formatBalances() + { + Currency euro = Currency.getInstance("EUR"); + + assertEquals("1", Utils.formatBalanceWithoutCurrencySymbol(new BigDecimal("1"), null)); + assertEquals("1.00", Utils.formatBalanceWithoutCurrencySymbol(new BigDecimal("1"), euro)); + + assertEquals("25", Utils.formatBalanceWithoutCurrencySymbol(new BigDecimal("25"), null)); + assertEquals("25.00", Utils.formatBalanceWithoutCurrencySymbol(new BigDecimal("25"), euro)); + + assertEquals("2", Utils.formatBalanceWithoutCurrencySymbol(new BigDecimal("2.5"), null)); + assertEquals("2.50", Utils.formatBalanceWithoutCurrencySymbol(new BigDecimal("2.5"), euro)); + + assertEquals("2", Utils.formatBalanceWithoutCurrencySymbol(new BigDecimal("2.05"), null)); + assertEquals("2.05", Utils.formatBalanceWithoutCurrencySymbol(new BigDecimal("2.05"), euro)); + + assertEquals("2", Utils.formatBalanceWithoutCurrencySymbol(new BigDecimal("2.50"), null)); + assertEquals("2.50", Utils.formatBalanceWithoutCurrencySymbol(new BigDecimal("2.50"), euro)); + + assertEquals("995", Utils.formatBalanceWithoutCurrencySymbol(new BigDecimal("995"), null)); + assertEquals("995.00", Utils.formatBalanceWithoutCurrencySymbol(new BigDecimal("995"), euro)); + + assertEquals("10", Utils.formatBalanceWithoutCurrencySymbol(new BigDecimal("9.95"), null)); + assertEquals("9.95", Utils.formatBalanceWithoutCurrencySymbol(new BigDecimal("9.95"), euro)); + + assertEquals("1,234", Utils.formatBalanceWithoutCurrencySymbol(new BigDecimal("1234"), null)); + assertEquals("1,234.00", Utils.formatBalanceWithoutCurrencySymbol(new BigDecimal("1234"), euro)); + + assertEquals("1,234", Utils.formatBalanceWithoutCurrencySymbol(new BigDecimal("1234.00"), null)); + assertEquals("1,234.00", Utils.formatBalanceWithoutCurrencySymbol(new BigDecimal("1234.00"), euro)); } } \ No newline at end of file