diff --git a/app/src/main/java/protect/card_locker/LoyaltyCardEditActivity.java b/app/src/main/java/protect/card_locker/LoyaltyCardEditActivity.java index 7e922facc..d5b2fc853 100644 --- a/app/src/main/java/protect/card_locker/LoyaltyCardEditActivity.java +++ b/app/src/main/java/protect/card_locker/LoyaltyCardEditActivity.java @@ -214,11 +214,11 @@ public class LoyaltyCardEditActivity extends AppCompatActivity hasChanged = true; try { - BigDecimal balance = Utils.parseCurrencyInUserLocale(s.toString()); + BigDecimal balance = Utils.parseCurrency(s.toString()); validBalance = true; balanceField.setTag(balance); - } catch (ParseException | NumberFormatException e) { + } catch (NumberFormatException e) { validBalance = false; e.printStackTrace(); } @@ -500,13 +500,10 @@ public class LoyaltyCardEditActivity extends AppCompatActivity break; } } - chip.setOnTouchListener(new View.OnTouchListener() { - @Override - public boolean onTouch(View v, MotionEvent event) { - hasChanged = true; + chip.setOnTouchListener((v, event) -> { + hasChanged = true; - return false; - } + return false; }); groupsChips.addView(chip); @@ -565,12 +562,7 @@ public class LoyaltyCardEditActivity extends AppCompatActivity barcodeTypeField.setAdapter(barcodeAdapter); FloatingActionButton saveButton = findViewById(R.id.fabSave); - saveButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - doSave(); - } - }); + saveButton.setOnClickListener(v -> doSave()); generateIcon(storeFieldEdit.getText().toString()); } diff --git a/app/src/main/java/protect/card_locker/Utils.java b/app/src/main/java/protect/card_locker/Utils.java index abbfb2edb..468555e8c 100644 --- a/app/src/main/java/protect/card_locker/Utils.java +++ b/app/src/main/java/protect/card_locker/Utils.java @@ -13,6 +13,7 @@ import java.util.Calendar; import java.util.Currency; import java.util.Date; import java.util.GregorianCalendar; +import java.util.List; import java.util.Locale; import androidx.core.graphics.ColorUtils; @@ -111,15 +112,17 @@ public class Utils { return numberFormat.format(value); } - static public BigDecimal parseCurrencyInUserLocale(String value) throws ParseException, NumberFormatException { - // BigDecimal only likes to parse in US locale - // So we have to translate whatever the input was to US locale - NumberFormat numberInputFormat = NumberFormat.getNumberInstance(); - NumberFormat numberToBigDecimalFormat = NumberFormat.getNumberInstance(Locale.US); + static public BigDecimal parseCurrency(String value) throws NumberFormatException { + // 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(',', '.'); - // BigDecimal won't understand values like 1,000 instead of 1000 - numberToBigDecimalFormat.setGroupingUsed(false); + // 2. Remove all but the last dot + while (value.split("\\.").length > 2) { + value = value.replaceFirst("\\.", ""); + } - return new BigDecimal(numberToBigDecimalFormat.format(numberInputFormat.parse(value))); + // Parse as BigDecimal + return new BigDecimal(value); } } diff --git a/app/src/test/java/protect/card_locker/UtilsTest.java b/app/src/test/java/protect/card_locker/UtilsTest.java new file mode 100644 index 000000000..d38b766e4 --- /dev/null +++ b/app/src/test/java/protect/card_locker/UtilsTest.java @@ -0,0 +1,36 @@ +package protect.card_locker; + + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.robolectric.RobolectricTestRunner; +import org.robolectric.annotation.Config; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThrows; + +@RunWith(RobolectricTestRunner.class) +@Config(sdk = 23) +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()); + + 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("......................")); + } +} \ No newline at end of file