Format quota email currency values (#7605)

This commit is contained in:
João Jandre 2023-10-10 08:06:24 -03:00 committed by GitHub
parent 7e998f9228
commit 43aed45706
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 51 additions and 6 deletions

View File

@ -17,10 +17,12 @@
package org.apache.cloudstack.quota; package org.apache.cloudstack.quota;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.text.NumberFormat;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.concurrent.TimeUnit; 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.StringEscapeUtils;
import org.apache.commons.lang.text.StrSubstitutor; import org.apache.commons.lang.text.StrSubstitutor;
import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
@ -48,6 +51,7 @@ import com.cloud.user.AccountVO;
import com.cloud.user.UserVO; import com.cloud.user.UserVO;
import com.cloud.user.dao.AccountDao; import com.cloud.user.dao.AccountDao;
import com.cloud.user.dao.UserDao; import com.cloud.user.dao.UserDao;
import com.cloud.utils.NumbersUtil;
import com.cloud.utils.component.ManagerBase; import com.cloud.utils.component.ManagerBase;
import com.cloud.utils.db.TransactionLegacy; import com.cloud.utils.db.TransactionLegacy;
import java.util.HashSet; import java.util.HashSet;
@ -209,8 +213,14 @@ public class QuotaAlertManagerImpl extends ManagerBase implements QuotaAlertMana
userNames = userNames.substring(0, userNames.length() - 1); userNames = userNames.substring(0, userNames.length() - 1);
} }
final Map<String, String> subjectOptionMap = generateOptionMap(account, userNames, accountDomain, balance, usage, emailType, false); String currencySymbol = ObjectUtils.defaultIfNull(_configDao.getValue(QuotaConfig.QuotaCurrencySymbol.key()), QuotaConfig.QuotaCurrencySymbol.defaultValue());
final Map<String, String> bodyOptionMap = generateOptionMap(account, userNames, accountDomain, balance, usage, emailType, true); 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<String, String> subjectOptionMap = generateOptionMap(account, userNames, accountDomain, balanceStr, usageStr, emailType, false);
final Map<String, String> bodyOptionMap = generateOptionMap(account, userNames, accountDomain, balanceStr, usageStr, emailType, true);
if (s_logger.isDebugEnabled()) { if (s_logger.isDebugEnabled()) {
s_logger.debug(String.format("Sending quota alert with values: accountName [%s], accountID [%s], accountUsers [%s], domainName [%s], domainID [%s].", 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<String, String> generateOptionMap(AccountVO accountVO, String userNames, DomainVO domainVO, final BigDecimal balance, final BigDecimal usage, public Map<String, String> generateOptionMap(AccountVO accountVO, String userNames, DomainVO domainVO, final String balance, final String usage,
final QuotaConfig.QuotaEmailTemplateTypes emailType, boolean escapeHtml) { final QuotaConfig.QuotaEmailTemplateTypes emailType, boolean escapeHtml) {
final Map<String, String> optionMap = new HashMap<>(); final Map<String, String> optionMap = new HashMap<>();
optionMap.put("accountID", accountVO.getUuid()); optionMap.put("accountID", accountVO.getUuid());
optionMap.put("domainID", domainVO.getUuid()); optionMap.put("domainID", domainVO.getUuid());
optionMap.put("quotaBalance", QuotaConfig.QuotaCurrencySymbol.value() + " " + balance.toString()); optionMap.put("quotaBalance", balance);
if (emailType == QuotaEmailTemplateTypes.QUOTA_STATEMENT) { if (emailType == QuotaEmailTemplateTypes.QUOTA_STATEMENT) {
optionMap.put("quotaUsage", QuotaConfig.QuotaCurrencySymbol.value() + " " + usage.toString()); optionMap.put("quotaUsage", usage);
} }
if (escapeHtml) { if (escapeHtml) {

View File

@ -30,6 +30,9 @@ public interface QuotaConfig {
public static final ConfigKey<String> QuotaCurrencySymbol = new ConfigKey<String>("Advanced", String.class, "quota.currency.symbol", "$", public static final ConfigKey<String> QuotaCurrencySymbol = new ConfigKey<String>("Advanced", String.class, "quota.currency.symbol", "$",
"The symbol for the currency in use to measure usage.", true); "The symbol for the currency in use to measure usage.", true);
public static final ConfigKey<String> QuotaCurrencyLocale = new ConfigKey<String>("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<Integer> QuotaStatementPeriod = new ConfigKey<Integer>("Advanced", Integer.class, "quota.statement.period", "1", public static final ConfigKey<Integer> QuotaStatementPeriod = new ConfigKey<Integer>("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); "This variables define the statement generation interval. Values correspond to bimonthly=0, monthly=1, quarterly=2, half-yearly=3 and yearly=4.", true);

View File

@ -140,7 +140,7 @@ public class QuotaServiceImpl extends ManagerBase implements QuotaService, Confi
@Override @Override
public ConfigKey<?>[] getConfigKeys() { 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, QuotaSmtpUser, QuotaSmtpPassword, QuotaSmtpAuthType, QuotaSmtpSender, QuotaSmtpEnabledSecurityProtocols, QuotaSmtpUseStartTLS, QuotaActivationRuleTimeout, QuotaAccountEnabled,
QuotaEmailHeader, QuotaEmailFooter}; QuotaEmailHeader, QuotaEmailFooter};
} }

View File

@ -19,7 +19,9 @@
package com.cloud.utils; package com.cloud.utils;
import java.math.BigDecimal;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.text.NumberFormat;
import java.text.ParseException; import java.text.ParseException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.Date; import java.util.Date;
@ -147,6 +149,26 @@ public class NumbersUtil {
} }
} }
/**
* Formats a BigDecimal with the number formatter.
* @return
* <li>null if value is null;</li>
* <li>value.toString() if the numberFormat is null;</li>
* <li>the value formatted if both parameters are not null;</li>
*/
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) { public static int hash(long value) {
return (int)(value ^ (value >>> 32)); return (int)(value ^ (value >>> 32));
} }