Skip to content

Commit

Permalink
Add support for unlimited number of decimal places in commodities
Browse files Browse the repository at this point in the history
Add tests for Money/Commodity
Fix breaking build
  • Loading branch information
codinguser committed Nov 13, 2015
1 parent 7de49a1 commit 409114e
Show file tree
Hide file tree
Showing 4 changed files with 29 additions and 53 deletions.
7 changes: 1 addition & 6 deletions app/src/main/java/org/gnucash/android/model/Commodity.java
Original file line number Diff line number Diff line change
Expand Up @@ -179,12 +179,7 @@ public int getSmallestFractionDigits(){
* @throws IllegalArgumentException if the smallest fraction is not a power of 10
*/
public void setSmallestFraction(int smallestFraction) {
if (smallestFraction != 1 && smallestFraction != 10 && smallestFraction != 100
&& smallestFraction != 1000 && smallestFraction != 10000
&& smallestFraction != 1000000 ) //make sure we are not getting digits
this.mSmallestFraction = 100;
else
this.mSmallestFraction = smallestFraction;
this.mSmallestFraction = smallestFraction;
}

public int getQuoteFlag() {
Expand Down
42 changes: 4 additions & 38 deletions app/src/main/java/org/gnucash/android/model/Money.java
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ public Money(BigDecimal amount, Commodity commodity){
public Money(String amount, String currencyCode){
//commodity has to be set first
mCommodity = Commodity.getInstance(currencyCode);
setAmount(amount);
setAmount(new BigDecimal(amount));
}

/**
Expand Down Expand Up @@ -228,11 +228,7 @@ public long getNumerator() {
*/
public long getDenominator() {
int scale = getScale();
if (scale == 0){
return 0;
} else {
return Integer.numberOfTrailingZeros(scale);
}
return BigDecimal.ONE.scaleByPowerOfTen(scale).longValueExact();
}

/**
Expand Down Expand Up @@ -291,7 +287,7 @@ public String formattedString(Locale locale){
String symbol;
if (mCommodity.equals(Commodity.USD) && !locale.equals(Locale.US)) {
symbol = "US$";
} else if (mCommodity.equals(Commodity.EUR) {
} else if (mCommodity.equals(Commodity.EUR)) {
symbol = currency.getSymbol(Locale.GERMANY); //euro currency is pretty unique around the world
} else {
symbol = currency.getSymbol(Locale.US); // US locale has the best symbol formatting table.
Expand Down Expand Up @@ -336,16 +332,7 @@ public Money negate(){
private void setAmount(@NonNull BigDecimal amount) {
mAmount = amount.setScale(mCommodity.getSmallestFractionDigits(), ROUNDING_MODE);
}

/**
* Sets the amount value of this <code>Money</code> object
* The <code>amount</code> is parsed by the {@link BigDecimal} constructor
* @param amount {@link String} amount to be set
*/
private void setAmount(String amount){
setAmount(parseToDecimal(amount));
}


/**
* Returns a new <code>Money</code> object whose value is the sum of the values of
* this object and <code>addend</code>.
Expand Down Expand Up @@ -507,27 +494,6 @@ public int compareTo(@NonNull Money another) {
return mAmount.compareTo(another.mAmount);
}

/**
* Parses a Locale specific string into a number using format for {@link Locale#US}
* @param amountString Formatted String amount
* @return String amount formatted in the default locale
*/
public static BigDecimal parseToDecimal(String amountString){
char separator = new DecimalFormatSymbols(Locale.US).getGroupingSeparator();
amountString = amountString.replace(Character.toString(separator), "");
NumberFormat formatter = NumberFormat.getInstance(Locale.US);
if (formatter instanceof DecimalFormat) {
((DecimalFormat)formatter).setParseBigDecimal(true);
}
BigDecimal result = new BigDecimal(0);
try {
result = (BigDecimal) formatter.parse(amountString);
} catch (ParseException e) {
Crashlytics.logException(e);
}
return result;
}

/**
* Returns a new instance of {@link Money} object with the absolute value of the current object
* @return Money object with absolute value of this instance
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public class CommodityTest {

@Test
public void setSmallestFraction_shouldNotUseDigits(){
Commodity commodity = new Commodity("Test", "USD", 4);
Commodity commodity = new Commodity("Test", "USD", 100);
assertThat(commodity.getSmallestFraction()).isEqualTo(100);

commodity.setSmallestFraction(1000);
Expand All @@ -36,7 +36,7 @@ public void setSmallestFraction_shouldNotUseDigits(){

@Test
public void testSmallestFractionDigits(){
Commodity commodity = new Commodity("Test", "USD", 4);
Commodity commodity = new Commodity("Test", "USD", 100);
assertThat(commodity.getSmallestFractionDigits()).isEqualTo(2);

commodity.setSmallestFraction(10);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,18 +57,15 @@ public void testCreation(){

Money temp = new Money(amount, CURRENCY_CODE);
assertThat("12.25").isEqualTo(temp.toPlainString());
assertThat(temp.getNumerator()).isEqualTo(1225L);
assertThat(temp.getDenominator()).isEqualTo(100L);

Commodity commodity = Commodity.getInstance(CURRENCY_CODE);
temp = new Money(BigDecimal.TEN, commodity);

assertEquals("10", temp.asBigDecimal().toPlainString());
assertEquals("10.00", temp.asBigDecimal().toPlainString()); //decimal places for EUR currency
assertEquals(commodity, temp.getCommodity());

//test only Locale.US parsing even under different locale
Locale.setDefault(Locale.GERMANY);
amount = "12,25";
temp = new Money(amount, CURRENCY_CODE);
assertEquals("1225.00", temp.toPlainString());
assertThat("10").isNotEqualTo(temp.asBigDecimal().toPlainString());
}

@Test
Expand Down Expand Up @@ -134,6 +131,24 @@ public void testNegation(){
validateImmutability();
}

@Test
public void testFractionParts(){
Money money = new Money("14.15", "USD");
assertThat(money.getNumerator()).isEqualTo(1415L);
assertThat(money.getDenominator()).isEqualTo(100L);

money = new Money("125", "JPY");
assertThat(money.getNumerator()).isEqualTo(125L);
assertThat(money.getDenominator()).isEqualTo(1L);
}

@Test
public void nonMatchingCommodityFraction_shouldThrowException(){
Money money = new Money("12.345", "JPY");
assertThat(money.getNumerator()).isEqualTo(12L);
assertThat(money.getDenominator()).isEqualTo(1);
}

@Test
public void testPrinting(){
assertEquals(mMoneyInEur.asString(), mMoneyInEur.toPlainString());
Expand Down

0 comments on commit 409114e

Please sign in to comment.