Skip to content

Commit

Permalink
issue 118: Invoice formatter displays now correct currency symbol
Browse files Browse the repository at this point in the history
  • Loading branch information
Matias Aguero committed Oct 6, 2015
1 parent 7759b81 commit b764b9c
Show file tree
Hide file tree
Showing 2 changed files with 161 additions and 13 deletions.
Expand Up @@ -17,24 +17,22 @@
package org.killbill.billing.invoice.template.formatters;

import java.math.BigDecimal;
import java.text.NumberFormat;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.UUID;

import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.killbill.billing.callcontext.InternalTenantContext;
import org.killbill.billing.invoice.api.formatters.ResourceBundleFactory;
import org.killbill.billing.tenant.api.TenantInternalApi;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.killbill.billing.catalog.api.Currency;
import org.killbill.billing.currency.api.CurrencyConversion;
import org.killbill.billing.currency.api.CurrencyConversionApi;
Expand All @@ -45,10 +43,13 @@
import org.killbill.billing.invoice.api.InvoiceItemType;
import org.killbill.billing.invoice.api.InvoicePayment;
import org.killbill.billing.invoice.api.formatters.InvoiceFormatter;
import org.killbill.billing.invoice.api.formatters.ResourceBundleFactory;
import org.killbill.billing.invoice.model.CreditAdjInvoiceItem;
import org.killbill.billing.invoice.model.CreditBalanceAdjInvoiceItem;
import org.killbill.billing.invoice.model.DefaultInvoice;
import org.killbill.billing.util.template.translation.TranslatorConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.google.common.base.Objects;
import com.google.common.base.Strings;
Expand All @@ -71,6 +72,18 @@ public class DefaultInvoiceFormatter implements InvoiceFormatter {
private final InternalTenantContext context;
private final ResourceBundleFactory bundleFactory;

public static Map<java.util.Currency, Locale> currencyLocaleMap;
{
currencyLocaleMap = new HashMap<java.util.Currency, Locale>();
for (Locale localeItem : Locale.getAvailableLocales()) {
try {
java.util.Currency currency = java.util.Currency.getInstance(localeItem);
currencyLocaleMap.put(currency, localeItem);
}catch (Exception e){
}
}
}

public DefaultInvoiceFormatter(final TranslatorConfig config, final Invoice invoice, final Locale locale, final CurrencyConversionApi currencyConversionApi, final ResourceBundleFactory bundleFactory, final InternalTenantContext context) {
this.config = config;
this.invoice = invoice;
Expand Down Expand Up @@ -213,20 +226,35 @@ public BigDecimal getBalance() {

@Override
public String getFormattedChargedAmount() {
final NumberFormat number = NumberFormat.getCurrencyInstance(locale);
return number.format(getChargedAmount().doubleValue());
return getFormattedAmountByLocaleAndInvoiceCurrency(getChargedAmount());
}

@Override
public String getFormattedPaidAmount() {
final NumberFormat number = NumberFormat.getCurrencyInstance(locale);
return number.format(getPaidAmount().doubleValue());
return getFormattedAmountByLocaleAndInvoiceCurrency(getPaidAmount());
}

@Override
public String getFormattedBalance() {
final NumberFormat number = NumberFormat.getCurrencyInstance(locale);
return number.format(getBalance().doubleValue());
return getFormattedAmountByLocaleAndInvoiceCurrency(getBalance());
}

/**
* Returns the amount with the correct currency symbol
*
* @param amount
* @return
*/
private String getFormattedAmountByLocaleAndInvoiceCurrency(BigDecimal amount) {
final DecimalFormat number = (DecimalFormat) DecimalFormat.getCurrencyInstance(locale);

java.util.Currency currency = java.util.Currency.getInstance(invoice.getCurrency().toString());
DecimalFormatSymbols dfs = number.getDecimalFormatSymbols();
dfs.setInternationalCurrencySymbol(currency.getCurrencyCode());
dfs.setCurrencySymbol(currency.getSymbol(currencyLocaleMap.get(currency)));
number.setDecimalFormatSymbols(dfs);

return number.format(amount.doubleValue());
}

@Override
Expand Down
Expand Up @@ -34,7 +34,6 @@
import org.killbill.billing.invoice.api.InvoiceItemType;
import org.killbill.billing.invoice.api.InvoicePaymentType;
import org.killbill.billing.invoice.api.formatters.InvoiceFormatter;
import org.killbill.billing.invoice.api.formatters.InvoiceFormatterFactory;
import org.killbill.billing.invoice.api.formatters.ResourceBundleFactory.ResourceBundleType;
import org.killbill.billing.invoice.model.CreditAdjInvoiceItem;
import org.killbill.billing.invoice.model.CreditBalanceAdjInvoiceItem;
Expand Down Expand Up @@ -186,6 +185,127 @@ public void testFormattedAmount() throws Exception {
Locale.FRANCE);
}

@Test(groups = "fast")
public void testFormattedAmountFranceAndJPY() throws Exception {

final FixedPriceInvoiceItem fixedItem = new FixedPriceInvoiceItem(UUID.randomUUID(), UUID.randomUUID(), null, null,
UUID.randomUUID().toString(), UUID.randomUUID().toString(),
new LocalDate(), new BigDecimal("1500.00"), Currency.JPY);
final Invoice invoiceEUR = new DefaultInvoice(UUID.randomUUID(), new LocalDate(), new LocalDate(), Currency.JPY);
invoiceEUR.addInvoiceItem(fixedItem);

checkOutput(invoiceEUR,
"<tr>\n" +
" <td class=\"amount\"><strong>{{invoice.formattedChargedAmount}}</strong></td>\n" +
"</tr>\n" +
"<tr>\n" +
" <td class=\"amount\"><strong>{{invoice.formattedPaidAmount}}</strong></td>\n" +
"</tr>\n" +
"<tr>\n" +
" <td class=\"amount\"><strong>{{invoice.formattedBalance}}</strong></td>\n" +
"</tr>",
"<tr>\n" +
" <td class=\"amount\"><strong>1 500,00 ¥</strong></td>\n" +
"</tr>\n" +
"<tr>\n" +
" <td class=\"amount\"><strong>0,00 ¥</strong></td>\n" +
"</tr>\n" +
"<tr>\n" +
" <td class=\"amount\"><strong>1 500,00 ¥</strong></td>\n" +
"</tr>",
Locale.FRANCE);
}

@Test(groups = "fast")
public void testFormattedAmountUSAndEUR() throws Exception {
final FixedPriceInvoiceItem fixedItemEUR = new FixedPriceInvoiceItem(UUID.randomUUID(), UUID.randomUUID(), null, null,
UUID.randomUUID().toString(), UUID.randomUUID().toString(),
new LocalDate(), new BigDecimal("2635.14"), Currency.EUR);
final Invoice invoiceEUR = new DefaultInvoice(UUID.randomUUID(), new LocalDate(), new LocalDate(), Currency.EUR);
invoiceEUR.addInvoiceItem(fixedItemEUR);

checkOutput(invoiceEUR,
"<tr>\n" +
" <td class=\"amount\"><strong>{{invoice.formattedChargedAmount}}</strong></td>\n" +
"</tr>\n" +
"<tr>\n" +
" <td class=\"amount\"><strong>{{invoice.formattedPaidAmount}}</strong></td>\n" +
"</tr>\n" +
"<tr>\n" +
" <td class=\"amount\"><strong>{{invoice.formattedBalance}}</strong></td>\n" +
"</tr>",
"<tr>\n" +
" <td class=\"amount\"><strong>€2,635.14</strong></td>\n" +
"</tr>\n" +
"<tr>\n" +
" <td class=\"amount\"><strong>€0.00</strong></td>\n" +
"</tr>\n" +
"<tr>\n" +
" <td class=\"amount\"><strong>€2,635.14</strong></td>\n" +
"</tr>",
Locale.US);
}

@Test(groups = "fast")
public void testFormattedAmountUSAndBRL() throws Exception {
final FixedPriceInvoiceItem fixedItem = new FixedPriceInvoiceItem(UUID.randomUUID(), UUID.randomUUID(), null, null,
UUID.randomUUID().toString(), UUID.randomUUID().toString(),
new LocalDate(), new BigDecimal("2635.14"), Currency.BRL);
final Invoice invoice = new DefaultInvoice(UUID.randomUUID(), new LocalDate(), new LocalDate(), Currency.BRL);
invoice.addInvoiceItem(fixedItem);

checkOutput(invoice,
"<tr>\n" +
" <td class=\"amount\"><strong>{{invoice.formattedChargedAmount}}</strong></td>\n" +
"</tr>\n" +
"<tr>\n" +
" <td class=\"amount\"><strong>{{invoice.formattedPaidAmount}}</strong></td>\n" +
"</tr>\n" +
"<tr>\n" +
" <td class=\"amount\"><strong>{{invoice.formattedBalance}}</strong></td>\n" +
"</tr>",
"<tr>\n" +
" <td class=\"amount\"><strong>R$2,635.14</strong></td>\n" +
"</tr>\n" +
"<tr>\n" +
" <td class=\"amount\"><strong>R$0.00</strong></td>\n" +
"</tr>\n" +
"<tr>\n" +
" <td class=\"amount\"><strong>R$2,635.14</strong></td>\n" +
"</tr>",
Locale.US);
}

@Test(groups = "fast")
public void testFormattedAmountUSAndGBP() throws Exception {
final FixedPriceInvoiceItem fixedItemEUR = new FixedPriceInvoiceItem(UUID.randomUUID(), UUID.randomUUID(), null, null,
UUID.randomUUID().toString(), UUID.randomUUID().toString(),
new LocalDate(), new BigDecimal("1499.95"), Currency.GBP);
final Invoice invoiceEUR = new DefaultInvoice(UUID.randomUUID(), new LocalDate(), new LocalDate(), Currency.GBP);
invoiceEUR.addInvoiceItem(fixedItemEUR);

checkOutput(invoiceEUR,
"<tr>\n" +
" <td class=\"amount\"><strong>{{invoice.formattedChargedAmount}}</strong></td>\n" +
"</tr>\n" +
"<tr>\n" +
" <td class=\"amount\"><strong>{{invoice.formattedPaidAmount}}</strong></td>\n" +
"</tr>\n" +
"<tr>\n" +
" <td class=\"amount\"><strong>{{invoice.formattedBalance}}</strong></td>\n" +
"</tr>",
"<tr>\n" +
" <td class=\"amount\"><strong>£1,499.95</strong></td>\n" +
"</tr>\n" +
"<tr>\n" +
" <td class=\"amount\"><strong>£0.00</strong></td>\n" +
"</tr>\n" +
"<tr>\n" +
" <td class=\"amount\"><strong>£1,499.95</strong></td>\n" +
"</tr>",
Locale.US);
}

@Test(groups = "fast")
public void testProcessedCurrencyExists() throws Exception {
final Invoice invoice = new DefaultInvoice(UUID.randomUUID(), clock.getUTCNow(), UUID.randomUUID(), new Integer(234), new LocalDate(), new LocalDate(), Currency.BRL, Currency.USD, false);
Expand Down

0 comments on commit b764b9c

Please sign in to comment.