diff --git a/framework/quota/src/main/java/org/apache/cloudstack/quota/QuotaAlertManagerImpl.java b/framework/quota/src/main/java/org/apache/cloudstack/quota/QuotaAlertManagerImpl.java index 6be739919ea..555757ec847 100644 --- a/framework/quota/src/main/java/org/apache/cloudstack/quota/QuotaAlertManagerImpl.java +++ b/framework/quota/src/main/java/org/apache/cloudstack/quota/QuotaAlertManagerImpl.java @@ -17,10 +17,12 @@ package org.apache.cloudstack.quota; import java.math.BigDecimal; +import java.text.NumberFormat; import java.util.ArrayList; import java.util.Date; import java.util.HashMap; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.concurrent.TimeUnit; @@ -37,6 +39,7 @@ import org.apache.cloudstack.quota.vo.QuotaEmailTemplatesVO; import org.apache.commons.lang.StringEscapeUtils; import org.apache.commons.lang.text.StrSubstitutor; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.ObjectUtils; import org.apache.log4j.Logger; import org.springframework.stereotype.Component; @@ -48,6 +51,7 @@ import com.cloud.user.AccountVO; import com.cloud.user.UserVO; import com.cloud.user.dao.AccountDao; import com.cloud.user.dao.UserDao; +import com.cloud.utils.NumbersUtil; import com.cloud.utils.component.ManagerBase; import com.cloud.utils.db.TransactionLegacy; import java.util.HashSet; @@ -209,8 +213,14 @@ public class QuotaAlertManagerImpl extends ManagerBase implements QuotaAlertMana userNames = userNames.substring(0, userNames.length() - 1); } - final Map subjectOptionMap = generateOptionMap(account, userNames, accountDomain, balance, usage, emailType, false); - final Map bodyOptionMap = generateOptionMap(account, userNames, accountDomain, balance, usage, emailType, true); + String currencySymbol = ObjectUtils.defaultIfNull(_configDao.getValue(QuotaConfig.QuotaCurrencySymbol.key()), QuotaConfig.QuotaCurrencySymbol.defaultValue()); + NumberFormat localeFormat = getLocaleFormatIfCurrencyLocaleNotNull(); + + String balanceStr = String.format("%s %s", currencySymbol, NumbersUtil.formatBigDecimalAccordingToNumberFormat(balance, localeFormat)); + String usageStr = String.format("%s %s", currencySymbol, NumbersUtil.formatBigDecimalAccordingToNumberFormat(usage, localeFormat)); + + final Map subjectOptionMap = generateOptionMap(account, userNames, accountDomain, balanceStr, usageStr, emailType, false); + final Map bodyOptionMap = generateOptionMap(account, userNames, accountDomain, balanceStr, usageStr, emailType, true); if (s_logger.isDebugEnabled()) { s_logger.debug(String.format("Sending quota alert with values: accountName [%s], accountID [%s], accountUsers [%s], domainName [%s], domainID [%s].", @@ -238,19 +248,29 @@ public class QuotaAlertManagerImpl extends ManagerBase implements QuotaAlertMana } } + private NumberFormat getLocaleFormatIfCurrencyLocaleNotNull() { + String currencyLocale = _configDao.getValue(QuotaConfig.QuotaCurrencyLocale.key()); + NumberFormat localeFormat = null; + if (currencyLocale != null) { + Locale locale = Locale.forLanguageTag(currencyLocale); + localeFormat = NumberFormat.getNumberInstance(locale); + } + return localeFormat; + } + /* * * */ - public Map generateOptionMap(AccountVO accountVO, String userNames, DomainVO domainVO, final BigDecimal balance, final BigDecimal usage, + public Map generateOptionMap(AccountVO accountVO, String userNames, DomainVO domainVO, final String balance, final String usage, final QuotaConfig.QuotaEmailTemplateTypes emailType, boolean escapeHtml) { final Map optionMap = new HashMap<>(); optionMap.put("accountID", accountVO.getUuid()); optionMap.put("domainID", domainVO.getUuid()); - optionMap.put("quotaBalance", QuotaConfig.QuotaCurrencySymbol.value() + " " + balance.toString()); + optionMap.put("quotaBalance", balance); if (emailType == QuotaEmailTemplateTypes.QUOTA_STATEMENT) { - optionMap.put("quotaUsage", QuotaConfig.QuotaCurrencySymbol.value() + " " + usage.toString()); + optionMap.put("quotaUsage", usage); } if (escapeHtml) { diff --git a/framework/quota/src/main/java/org/apache/cloudstack/quota/constant/QuotaConfig.java b/framework/quota/src/main/java/org/apache/cloudstack/quota/constant/QuotaConfig.java index f1426f397b3..59aa54424cf 100644 --- a/framework/quota/src/main/java/org/apache/cloudstack/quota/constant/QuotaConfig.java +++ b/framework/quota/src/main/java/org/apache/cloudstack/quota/constant/QuotaConfig.java @@ -30,6 +30,9 @@ public interface QuotaConfig { public static final ConfigKey QuotaCurrencySymbol = new ConfigKey("Advanced", String.class, "quota.currency.symbol", "$", "The symbol for the currency in use to measure usage.", true); + public static final ConfigKey QuotaCurrencyLocale = new ConfigKey("Advanced", String.class, "quota.currency.locale", null, + "The location used for formatting the value (e.g. \"en-US\" for English or \"pt-BR\" for Brazilian Portuguese)", true); + public static final ConfigKey QuotaStatementPeriod = new ConfigKey("Advanced", Integer.class, "quota.statement.period", "1", "This variables define the statement generation interval. Values correspond to bimonthly=0, monthly=1, quarterly=2, half-yearly=3 and yearly=4.", true); diff --git a/plugins/database/quota/src/main/java/org/apache/cloudstack/quota/QuotaServiceImpl.java b/plugins/database/quota/src/main/java/org/apache/cloudstack/quota/QuotaServiceImpl.java index 1a4007ca5de..9179691e973 100644 --- a/plugins/database/quota/src/main/java/org/apache/cloudstack/quota/QuotaServiceImpl.java +++ b/plugins/database/quota/src/main/java/org/apache/cloudstack/quota/QuotaServiceImpl.java @@ -140,7 +140,7 @@ public class QuotaServiceImpl extends ManagerBase implements QuotaService, Confi @Override public ConfigKey[] getConfigKeys() { - return new ConfigKey[] {QuotaPluginEnabled, QuotaEnableEnforcement, QuotaCurrencySymbol, QuotaStatementPeriod, QuotaSmtpHost, QuotaSmtpPort, QuotaSmtpTimeout, + return new ConfigKey[] {QuotaPluginEnabled, QuotaEnableEnforcement, QuotaCurrencySymbol, QuotaCurrencyLocale, QuotaStatementPeriod, QuotaSmtpHost, QuotaSmtpPort, QuotaSmtpTimeout, QuotaSmtpUser, QuotaSmtpPassword, QuotaSmtpAuthType, QuotaSmtpSender, QuotaSmtpEnabledSecurityProtocols, QuotaSmtpUseStartTLS, QuotaActivationRuleTimeout, QuotaAccountEnabled, QuotaEmailHeader, QuotaEmailFooter}; } diff --git a/utils/src/main/java/com/cloud/utils/NumbersUtil.java b/utils/src/main/java/com/cloud/utils/NumbersUtil.java index 3d48344bb33..f1a2e863247 100644 --- a/utils/src/main/java/com/cloud/utils/NumbersUtil.java +++ b/utils/src/main/java/com/cloud/utils/NumbersUtil.java @@ -19,7 +19,9 @@ package com.cloud.utils; +import java.math.BigDecimal; import java.nio.ByteBuffer; +import java.text.NumberFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; @@ -147,6 +149,26 @@ public class NumbersUtil { } } + /** + * Formats a BigDecimal with the number formatter. + * @return + *
  • null if value is null;
  • + *
  • value.toString() if the numberFormat is null;
  • + *
  • the value formatted if both parameters are not null;
  • + */ + public static String formatBigDecimalAccordingToNumberFormat(BigDecimal value, NumberFormat numberFormat) { + if (value == null) { + return null; + } + + if (numberFormat == null) { + return value.toString(); + } + + return numberFormat.format(value); + } + + public static int hash(long value) { return (int)(value ^ (value >>> 32)); }