mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
parent
7b02c4cc48
commit
f76c6f3ea9
@ -69,3 +69,13 @@ CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.network_offerings','for_nsx', 'int(1
|
||||
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.network_offerings','nsx_mode', 'varchar(32) COMMENT "mode in which the network would route traffic"');
|
||||
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.vpc_offerings','for_nsx', 'int(1) unsigned DEFAULT "0" COMMENT "is nsx enabled for the resource"');
|
||||
CALL `cloud`.`IDEMPOTENT_ADD_COLUMN`('cloud.vpc_offerings','nsx_mode', 'varchar(32) COMMENT "mode in which the network would route traffic"');
|
||||
|
||||
|
||||
-- Create table to persist quota email template configurations
|
||||
CREATE TABLE IF NOT EXISTS `cloud_usage`.`quota_email_configuration`(
|
||||
`account_id` int(11) NOT NULL,
|
||||
`email_template_id` bigint(20) NOT NULL,
|
||||
`enabled` int(1) UNSIGNED NOT NULL,
|
||||
PRIMARY KEY (`account_id`, `email_template_id`),
|
||||
CONSTRAINT `FK_quota_email_configuration_account_id` FOREIGN KEY (`account_id`) REFERENCES `cloud_usage`.`quota_account`(`account_id`),
|
||||
CONSTRAINT `FK_quota_email_configuration_email_template_id` FOREIGN KEY (`email_template_id`) REFERENCES `cloud_usage`.`quota_email_templates`(`id`));
|
||||
|
||||
@ -16,11 +16,14 @@
|
||||
//under the License.
|
||||
package org.apache.cloudstack.quota;
|
||||
|
||||
import com.cloud.user.AccountVO;
|
||||
import com.cloud.utils.component.Manager;
|
||||
|
||||
import org.apache.cloudstack.quota.QuotaAlertManagerImpl.DeferredQuotaEmail;
|
||||
import org.apache.cloudstack.quota.constant.QuotaConfig;
|
||||
|
||||
public interface QuotaAlertManager extends Manager {
|
||||
boolean isQuotaEmailTypeEnabledForAccount(AccountVO account, QuotaConfig.QuotaEmailTemplateTypes quotaEmailTemplateType);
|
||||
void checkAndSendQuotaAlertEmails();
|
||||
void sendQuotaAlert(DeferredQuotaEmail emailToBeSent);
|
||||
}
|
||||
|
||||
@ -34,8 +34,10 @@ import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||
import org.apache.cloudstack.quota.constant.QuotaConfig;
|
||||
import org.apache.cloudstack.quota.constant.QuotaConfig.QuotaEmailTemplateTypes;
|
||||
import org.apache.cloudstack.quota.dao.QuotaAccountDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaEmailConfigurationDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaEmailTemplatesDao;
|
||||
import org.apache.cloudstack.quota.vo.QuotaAccountVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaEmailConfigurationVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaEmailTemplatesVO;
|
||||
import org.apache.commons.lang.StringEscapeUtils;
|
||||
import org.apache.commons.lang.text.StrSubstitutor;
|
||||
@ -80,7 +82,10 @@ public class QuotaAlertManagerImpl extends ManagerBase implements QuotaAlertMana
|
||||
@Inject
|
||||
private QuotaManager _quotaManager;
|
||||
|
||||
private boolean _lockAccountEnforcement = false;
|
||||
@Inject
|
||||
private QuotaEmailConfigurationDao quotaEmailConfigurationDao;
|
||||
|
||||
protected boolean _lockAccountEnforcement = false;
|
||||
private String senderAddress;
|
||||
protected SMTPMailSender mailSender;
|
||||
|
||||
@ -139,53 +144,98 @@ public class QuotaAlertManagerImpl extends ManagerBase implements QuotaAlertMana
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether a Quota email type is enabled or not for the provided account.
|
||||
*/
|
||||
@Override
|
||||
public boolean isQuotaEmailTypeEnabledForAccount(AccountVO account, QuotaEmailTemplateTypes quotaEmailTemplateType) {
|
||||
boolean quotaEmailsEnabled = QuotaConfig.QuotaEnableEmails.valueIn(account.getAccountId());
|
||||
if (!quotaEmailsEnabled) {
|
||||
logger.debug("Configuration [{}] is disabled for account [{}]. Therefore, the account will not receive Quota email of type [{}].", QuotaConfig.QuotaEnableEmails.key(), account, quotaEmailTemplateType);
|
||||
return false;
|
||||
}
|
||||
|
||||
QuotaEmailConfigurationVO quotaEmail = quotaEmailConfigurationDao.findByAccountIdAndEmailTemplateType(account.getAccountId(), quotaEmailTemplateType);
|
||||
|
||||
boolean emailEnabled = quotaEmail == null || quotaEmail.isEnabled();
|
||||
if (emailEnabled) {
|
||||
logger.debug("Quota email [{}] is enabled for account [{}].", quotaEmailTemplateType, account);
|
||||
} else {
|
||||
logger.debug("Quota email [{}] has been manually disabled for account [{}] through the API quotaConfigureEmail.", quotaEmailTemplateType, account);
|
||||
}
|
||||
return emailEnabled;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void checkAndSendQuotaAlertEmails() {
|
||||
List<DeferredQuotaEmail> deferredQuotaEmailList = new ArrayList<DeferredQuotaEmail>();
|
||||
final BigDecimal zeroBalance = new BigDecimal(0);
|
||||
|
||||
logger.info("Checking and sending quota alert emails.");
|
||||
for (final QuotaAccountVO quotaAccount : _quotaAcc.listAllQuotaAccount()) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("checkAndSendQuotaAlertEmails accId=" + quotaAccount.getId());
|
||||
checkQuotaAlertEmailForAccount(deferredQuotaEmailList, quotaAccount);
|
||||
}
|
||||
|
||||
for (DeferredQuotaEmail emailToBeSent : deferredQuotaEmailList) {
|
||||
logger.debug("Attempting to send a quota alert email to users of account [{}].", emailToBeSent.getAccount().getAccountName());
|
||||
sendQuotaAlert(emailToBeSent);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks a given quota account to see if they should receive any emails. First by checking if it has any balance at all, if its account can be found, then checks
|
||||
* if they should receive either QUOTA_EMPTY or QUOTA_LOW emails, taking into account if these email templates are disabled or not for that account.
|
||||
* */
|
||||
protected void checkQuotaAlertEmailForAccount(List<DeferredQuotaEmail> deferredQuotaEmailList, QuotaAccountVO quotaAccount) {
|
||||
logger.debug("Checking {} for email alerts.", quotaAccount);
|
||||
BigDecimal accountBalance = quotaAccount.getQuotaBalance();
|
||||
|
||||
if (accountBalance == null) {
|
||||
logger.debug("{} has a null balance, therefore it will not receive quota alert emails.", quotaAccount);
|
||||
return;
|
||||
}
|
||||
|
||||
AccountVO account = _accountDao.findById(quotaAccount.getId());
|
||||
if (account == null) {
|
||||
logger.debug("Account of {} is removed, thus it will not receive quota alert emails.", quotaAccount);
|
||||
return;
|
||||
}
|
||||
|
||||
checkBalanceAndAddToEmailList(deferredQuotaEmailList, quotaAccount, account, accountBalance);
|
||||
}
|
||||
|
||||
private void checkBalanceAndAddToEmailList(List<DeferredQuotaEmail> deferredQuotaEmailList, QuotaAccountVO quotaAccount, AccountVO account, BigDecimal accountBalance) {
|
||||
Date balanceDate = quotaAccount.getQuotaBalanceDate();
|
||||
Date alertDate = quotaAccount.getQuotaAlertDate();
|
||||
int lockable = quotaAccount.getQuotaEnforce();
|
||||
BigDecimal thresholdBalance = quotaAccount.getQuotaMinBalance();
|
||||
if (accountBalance != null) {
|
||||
AccountVO account = _accountDao.findById(quotaAccount.getId());
|
||||
if (account == null) {
|
||||
continue; // the account is removed
|
||||
}
|
||||
logger.debug("checkAndSendQuotaAlertEmails: Check id={} bal={}, alertDate={}, lockable={}", account.getId(),
|
||||
accountBalance, DateUtil.displayDateInTimezone(QuotaManagerImpl.getUsageAggregationTimeZone(), alertDate),
|
||||
lockable);
|
||||
if (accountBalance.compareTo(zeroBalance) < 0) {
|
||||
if (_lockAccountEnforcement && (lockable == 1)) {
|
||||
if (_quotaManager.isLockable(account)) {
|
||||
logger.info("Locking account " + account.getAccountName() + " due to quota < 0.");
|
||||
|
||||
logger.debug("Checking {} with accountBalance [{}], alertDate [{}] and lockable [{}] to see if a quota alert email should be sent.", account,
|
||||
accountBalance, DateUtil.displayDateInTimezone(QuotaManagerImpl.getUsageAggregationTimeZone(), alertDate), lockable);
|
||||
|
||||
boolean shouldSendEmail = alertDate == null || (balanceDate.after(alertDate) && getDifferenceDays(alertDate, new Date()) > 1);
|
||||
|
||||
if (accountBalance.compareTo(BigDecimal.ZERO) < 0) {
|
||||
if (_lockAccountEnforcement && lockable == 1 && _quotaManager.isLockable(account)) {
|
||||
logger.info("Locking {}, as quota balance is lower than 0.", account);
|
||||
lockAccount(account.getId());
|
||||
}
|
||||
}
|
||||
if (alertDate == null || (balanceDate.after(alertDate) && getDifferenceDays(alertDate, new Date()) > 1)) {
|
||||
logger.info("Sending alert " + account.getAccountName() + " due to quota < 0.");
|
||||
deferredQuotaEmailList.add(new DeferredQuotaEmail(account, quotaAccount, QuotaConfig.QuotaEmailTemplateTypes.QUOTA_EMPTY));
|
||||
|
||||
boolean quotaEmptyEmailEnabled = isQuotaEmailTypeEnabledForAccount(account, QuotaEmailTemplateTypes.QUOTA_EMPTY);
|
||||
if (quotaEmptyEmailEnabled && shouldSendEmail) {
|
||||
logger.debug("Adding {} to the deferred emails list, as quota balance is lower than 0.", account);
|
||||
deferredQuotaEmailList.add(new DeferredQuotaEmail(account, quotaAccount, QuotaEmailTemplateTypes.QUOTA_EMPTY));
|
||||
return;
|
||||
}
|
||||
} else if (accountBalance.compareTo(thresholdBalance) < 0) {
|
||||
if (alertDate == null || (balanceDate.after(alertDate) && getDifferenceDays(alertDate, new Date()) > 1)) {
|
||||
logger.info("Sending alert " + account.getAccountName() + " due to quota below threshold.");
|
||||
deferredQuotaEmailList.add(new DeferredQuotaEmail(account, quotaAccount, QuotaConfig.QuotaEmailTemplateTypes.QUOTA_LOW));
|
||||
boolean quotaLowEmailEnabled = isQuotaEmailTypeEnabledForAccount(account, QuotaEmailTemplateTypes.QUOTA_LOW);
|
||||
if (quotaLowEmailEnabled && shouldSendEmail) {
|
||||
logger.debug("Adding {} to the deferred emails list, as quota balance [{}] is below the threshold [{}].", account, accountBalance, thresholdBalance);
|
||||
deferredQuotaEmailList.add(new DeferredQuotaEmail(account, quotaAccount, QuotaEmailTemplateTypes.QUOTA_LOW));
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (DeferredQuotaEmail emailToBeSent : deferredQuotaEmailList) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("checkAndSendQuotaAlertEmails: Attempting to send quota alert email to users of account: " + emailToBeSent.getAccount().getAccountName());
|
||||
}
|
||||
sendQuotaAlert(emailToBeSent);
|
||||
}
|
||||
logger.debug("{} will not receive any quota alert emails in this round.", account);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -285,7 +335,7 @@ public class QuotaAlertManagerImpl extends ManagerBase implements QuotaAlertMana
|
||||
return optionMap;
|
||||
}
|
||||
|
||||
public static long getDifferenceDays(Date d1, Date d2) {
|
||||
public long getDifferenceDays(Date d1, Date d2) {
|
||||
long diff = d2.getTime() - d1.getTime();
|
||||
return TimeUnit.DAYS.convert(diff, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
|
||||
@ -31,6 +31,8 @@ import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||
import org.apache.cloudstack.quota.QuotaAlertManagerImpl.DeferredQuotaEmail;
|
||||
import org.apache.cloudstack.quota.constant.QuotaConfig;
|
||||
import org.apache.cloudstack.quota.dao.QuotaAccountDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaEmailConfigurationDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaEmailTemplatesDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaUsageDao;
|
||||
import org.apache.cloudstack.quota.vo.QuotaAccountVO;
|
||||
import org.springframework.stereotype.Component;
|
||||
@ -53,6 +55,12 @@ public class QuotaStatementImpl extends ManagerBase implements QuotaStatement {
|
||||
@Inject
|
||||
private ConfigurationDao _configDao;
|
||||
|
||||
@Inject
|
||||
private QuotaEmailConfigurationDao quotaEmailConfigurationDao;
|
||||
|
||||
@Inject
|
||||
private QuotaEmailTemplatesDao quotaEmailTemplatesDao;
|
||||
|
||||
final public static int s_LAST_STATEMENT_SENT_DAYS = 6; //ideally should be less than 7 days
|
||||
|
||||
public enum QuotaStatementPeriods {
|
||||
@ -111,29 +119,34 @@ public class QuotaStatementImpl extends ManagerBase implements QuotaStatement {
|
||||
if (quotaAccount.getQuotaBalance() == null) {
|
||||
continue; // no quota usage for this account ever, ignore
|
||||
}
|
||||
AccountVO account = _accountDao.findById(quotaAccount.getId());
|
||||
if (account == null) {
|
||||
logger.debug("Could not find an account corresponding to [{}]. Therefore, the statement email will not be sent.", quotaAccount);
|
||||
continue;
|
||||
}
|
||||
|
||||
boolean quotaStatementEmailEnabled = _quotaAlert.isQuotaEmailTypeEnabledForAccount(account, QuotaConfig.QuotaEmailTemplateTypes.QUOTA_STATEMENT);
|
||||
if (!quotaStatementEmailEnabled) {
|
||||
logger.debug("{} has [{}] email disabled. Therefore the email will not be sent.", quotaAccount, QuotaConfig.QuotaEmailTemplateTypes.QUOTA_STATEMENT);
|
||||
continue;
|
||||
}
|
||||
|
||||
//check if it is statement time
|
||||
Calendar interval[] = statementTime(Calendar.getInstance(), _period);
|
||||
|
||||
Date lastStatementDate = quotaAccount.getLastStatementDate();
|
||||
if (interval != null) {
|
||||
AccountVO account = _accountDao.findById(quotaAccount.getId());
|
||||
if (account != null) {
|
||||
if (lastStatementDate == null || getDifferenceDays(lastStatementDate, new Date()) >= s_LAST_STATEMENT_SENT_DAYS + 1) {
|
||||
BigDecimal quotaUsage = _quotaUsage.findTotalQuotaUsage(account.getAccountId(), account.getDomainId(), null, interval[0].getTime(), interval[1].getTime());
|
||||
logger.info("For account=" + quotaAccount.getId() + ", quota used = " + quotaUsage);
|
||||
logger.info("Quota statement for account [{}] has an usage of [{}].", quotaAccount, quotaUsage);
|
||||
|
||||
// send statement
|
||||
deferredQuotaEmailList.add(new DeferredQuotaEmail(account, quotaAccount, quotaUsage, QuotaConfig.QuotaEmailTemplateTypes.QUOTA_STATEMENT));
|
||||
} else {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("For " + quotaAccount.getId() + " the statement has been sent recently");
|
||||
|
||||
}
|
||||
}
|
||||
logger.debug("Quota statement has already been sent recently to account [{}].", quotaAccount);
|
||||
}
|
||||
} else if (lastStatementDate != null) {
|
||||
logger.info("For " + quotaAccount.getId() + " it is already more than " + getDifferenceDays(lastStatementDate, new Date())
|
||||
+ " days, will send statement in next cycle");
|
||||
logger.info("For account {} it is already more than {} days, will send statement in next cycle.", quotaAccount.getId(), getDifferenceDays(lastStatementDate, new Date()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -72,6 +72,9 @@ public interface QuotaConfig {
|
||||
ConfigKey<String> QuotaEmailFooter = new ConfigKey<>("Advanced", String.class, "quota.email.footer", "",
|
||||
"Text to be added as a footer for quota emails. Line breaks are not automatically inserted between this section and the body.", true, ConfigKey.Scope.Domain);
|
||||
|
||||
ConfigKey<Boolean> QuotaEnableEmails = new ConfigKey<>("Advanced", Boolean.class, "quota.enable.emails", "true",
|
||||
"Indicates whether Quota emails should be sent or not to accounts. When enabled, the behavior for each account can be overridden through the API quotaConfigureEmail.", true, ConfigKey.Scope.Account);
|
||||
|
||||
enum QuotaEmailTemplateTypes {
|
||||
QUOTA_LOW, QUOTA_EMPTY, QUOTA_UNLOCK_ACCOUNT, QUOTA_STATEMENT
|
||||
}
|
||||
|
||||
@ -0,0 +1,36 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package org.apache.cloudstack.quota.dao;
|
||||
|
||||
import com.cloud.utils.db.GenericDao;
|
||||
import org.apache.cloudstack.quota.constant.QuotaConfig;
|
||||
import org.apache.cloudstack.quota.vo.QuotaEmailConfigurationVO;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public interface QuotaEmailConfigurationDao extends GenericDao<QuotaEmailConfigurationVO, Long> {
|
||||
|
||||
QuotaEmailConfigurationVO findByAccountIdAndEmailTemplateId(long accountId, long emailTemplateId);
|
||||
|
||||
QuotaEmailConfigurationVO updateQuotaEmailConfiguration(QuotaEmailConfigurationVO quotaEmailConfigurationVO);
|
||||
|
||||
void persistQuotaEmailConfiguration(QuotaEmailConfigurationVO quotaEmailConfigurationVO);
|
||||
|
||||
List<QuotaEmailConfigurationVO> listByAccount(long accountId);
|
||||
|
||||
QuotaEmailConfigurationVO findByAccountIdAndEmailTemplateType(long accountId, QuotaConfig.QuotaEmailTemplateTypes quotaEmailTemplateType);
|
||||
}
|
||||
@ -0,0 +1,105 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package org.apache.cloudstack.quota.dao;
|
||||
|
||||
import com.cloud.utils.db.GenericDaoBase;
|
||||
import com.cloud.utils.db.JoinBuilder;
|
||||
import com.cloud.utils.db.SearchBuilder;
|
||||
import com.cloud.utils.db.SearchCriteria;
|
||||
import com.cloud.utils.db.Transaction;
|
||||
import com.cloud.utils.db.TransactionCallback;
|
||||
import com.cloud.utils.db.TransactionLegacy;
|
||||
import org.apache.cloudstack.quota.constant.QuotaConfig;
|
||||
import org.apache.cloudstack.quota.vo.QuotaEmailConfigurationVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaEmailTemplatesVO;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.annotation.PostConstruct;
|
||||
import javax.inject.Inject;
|
||||
import java.util.List;
|
||||
|
||||
@Component
|
||||
public class QuotaEmailConfigurationDaoImpl extends GenericDaoBase<QuotaEmailConfigurationVO, Long> implements QuotaEmailConfigurationDao {
|
||||
|
||||
@Inject
|
||||
private QuotaEmailTemplatesDao quotaEmailTemplatesDao;
|
||||
|
||||
private SearchBuilder<QuotaEmailConfigurationVO> searchBuilderFindByIds;
|
||||
|
||||
private SearchBuilder<QuotaEmailTemplatesVO> searchBuilderFindByTemplateName;
|
||||
|
||||
private SearchBuilder<QuotaEmailConfigurationVO> searchBuilderFindByTemplateTypeAndAccountId;
|
||||
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
searchBuilderFindByIds = createSearchBuilder();
|
||||
searchBuilderFindByIds.and("account_id", searchBuilderFindByIds.entity().getAccountId(), SearchCriteria.Op.EQ);
|
||||
searchBuilderFindByIds.and("email_template_id", searchBuilderFindByIds.entity().getEmailTemplateId(), SearchCriteria.Op.EQ);
|
||||
searchBuilderFindByIds.done();
|
||||
|
||||
searchBuilderFindByTemplateName = quotaEmailTemplatesDao.createSearchBuilder();
|
||||
searchBuilderFindByTemplateName.and("template_name", searchBuilderFindByTemplateName.entity().getTemplateName(), SearchCriteria.Op.EQ);
|
||||
|
||||
searchBuilderFindByTemplateTypeAndAccountId = createSearchBuilder();
|
||||
searchBuilderFindByTemplateTypeAndAccountId.and("account_id", searchBuilderFindByTemplateTypeAndAccountId.entity().getAccountId(), SearchCriteria.Op.EQ);
|
||||
searchBuilderFindByTemplateTypeAndAccountId.join("email_template_id", searchBuilderFindByTemplateName, searchBuilderFindByTemplateName.entity().getId(),
|
||||
searchBuilderFindByTemplateTypeAndAccountId.entity().getEmailTemplateId(), JoinBuilder.JoinType.INNER);
|
||||
|
||||
searchBuilderFindByTemplateName.done();
|
||||
searchBuilderFindByTemplateTypeAndAccountId.done();
|
||||
}
|
||||
|
||||
@Override
|
||||
public QuotaEmailConfigurationVO findByAccountIdAndEmailTemplateId(long accountId, long emailTemplateId) {
|
||||
SearchCriteria<QuotaEmailConfigurationVO> sc = searchBuilderFindByIds.create();
|
||||
sc.setParameters("account_id", accountId);
|
||||
sc.setParameters("email_template_id", emailTemplateId);
|
||||
return Transaction.execute(TransactionLegacy.USAGE_DB, (TransactionCallback<QuotaEmailConfigurationVO>) status -> findOneBy(sc));
|
||||
}
|
||||
|
||||
@Override
|
||||
public QuotaEmailConfigurationVO updateQuotaEmailConfiguration(QuotaEmailConfigurationVO quotaEmailConfigurationVO) {
|
||||
SearchCriteria<QuotaEmailConfigurationVO> sc = searchBuilderFindByIds.create();
|
||||
sc.setParameters("account_id", quotaEmailConfigurationVO.getAccountId());
|
||||
sc.setParameters("email_template_id", quotaEmailConfigurationVO.getEmailTemplateId());
|
||||
Transaction.execute(TransactionLegacy.USAGE_DB, (TransactionCallback<Integer>) status -> update(quotaEmailConfigurationVO, sc));
|
||||
|
||||
return quotaEmailConfigurationVO;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void persistQuotaEmailConfiguration(QuotaEmailConfigurationVO quotaEmailConfigurationVO) {
|
||||
Transaction.execute(TransactionLegacy.USAGE_DB, (TransactionCallback<QuotaEmailConfigurationVO>) status -> persist(quotaEmailConfigurationVO));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<QuotaEmailConfigurationVO> listByAccount(long accountId) {
|
||||
SearchCriteria<QuotaEmailConfigurationVO> sc = searchBuilderFindByIds.create();
|
||||
sc.setParameters("account_id", accountId);
|
||||
|
||||
return Transaction.execute(TransactionLegacy.USAGE_DB, (TransactionCallback<List<QuotaEmailConfigurationVO>>) status -> listBy(sc));
|
||||
}
|
||||
|
||||
@Override
|
||||
public QuotaEmailConfigurationVO findByAccountIdAndEmailTemplateType(long accountId, QuotaConfig.QuotaEmailTemplateTypes quotaEmailTemplateType) {
|
||||
SearchCriteria<QuotaEmailConfigurationVO> sc = searchBuilderFindByTemplateTypeAndAccountId.create();
|
||||
sc.setParameters("account_id", accountId);
|
||||
sc.setJoinParameters("email_template_id", "template_name", quotaEmailTemplateType.toString());
|
||||
|
||||
return Transaction.execute(TransactionLegacy.USAGE_DB, (TransactionCallback<QuotaEmailConfigurationVO>) status -> findOneBy(sc));
|
||||
}
|
||||
}
|
||||
@ -24,4 +24,6 @@ import java.util.List;
|
||||
public interface QuotaEmailTemplatesDao extends GenericDao<QuotaEmailTemplatesVO, Long> {
|
||||
List<QuotaEmailTemplatesVO> listAllQuotaEmailTemplates(String templateName);
|
||||
boolean updateQuotaEmailTemplate(QuotaEmailTemplatesVO template);
|
||||
|
||||
QuotaEmailTemplatesVO findById(long id);
|
||||
}
|
||||
|
||||
@ -66,4 +66,9 @@ public class QuotaEmailTemplatesDaoImpl extends GenericDaoBase<QuotaEmailTemplat
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public QuotaEmailTemplatesVO findById(long id) {
|
||||
return Transaction.execute(TransactionLegacy.USAGE_DB, (TransactionCallback<QuotaEmailTemplatesVO>) status -> QuotaEmailTemplatesDaoImpl.super.findById(id));
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,68 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
package org.apache.cloudstack.quota.vo;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.Table;
|
||||
|
||||
@Entity
|
||||
@Table(name = "quota_email_configuration")
|
||||
public class QuotaEmailConfigurationVO {
|
||||
|
||||
@Column(name = "account_id")
|
||||
private long accountId;
|
||||
|
||||
@Column(name = "email_template_id")
|
||||
private long emailTemplateId;
|
||||
|
||||
@Column(name = "enabled")
|
||||
private boolean enabled;
|
||||
|
||||
public QuotaEmailConfigurationVO() {
|
||||
}
|
||||
|
||||
public QuotaEmailConfigurationVO(long accountId, long emailTemplateId, boolean enable) {
|
||||
this.accountId = accountId;
|
||||
this.emailTemplateId = emailTemplateId;
|
||||
this.enabled = enable;
|
||||
}
|
||||
|
||||
public long getAccountId() {
|
||||
return accountId;
|
||||
}
|
||||
|
||||
public void setAccountId(long accountId) {
|
||||
this.accountId = accountId;
|
||||
}
|
||||
|
||||
public long getEmailTemplateId() {
|
||||
return emailTemplateId;
|
||||
}
|
||||
|
||||
public void setEmailTemplateId(long emailTemplateId) {
|
||||
this.emailTemplateId = emailTemplateId;
|
||||
}
|
||||
|
||||
public boolean isEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
}
|
||||
@ -30,5 +30,6 @@
|
||||
<bean id="QuotaManager" class="org.apache.cloudstack.quota.QuotaManagerImpl" />
|
||||
<bean id="QuotaAlertManager" class="org.apache.cloudstack.quota.QuotaAlertManagerImpl" />
|
||||
<bean id="QuotaStatement" class="org.apache.cloudstack.quota.QuotaStatementImpl" />
|
||||
<bean id="QuotaEmailConfigurationDao" class="org.apache.cloudstack.quota.dao.QuotaEmailConfigurationDaoImpl"/>
|
||||
|
||||
</beans>
|
||||
|
||||
@ -30,9 +30,12 @@ import javax.naming.ConfigurationException;
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||
import org.apache.cloudstack.quota.constant.QuotaConfig;
|
||||
import org.apache.cloudstack.quota.dao.QuotaAccountDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaEmailConfigurationDaoImpl;
|
||||
import org.apache.cloudstack.quota.dao.QuotaEmailTemplatesDao;
|
||||
import org.apache.cloudstack.quota.vo.QuotaAccountVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaEmailConfigurationVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaEmailTemplatesVO;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@ -71,6 +74,9 @@ public class QuotaAlertManagerImplTest extends TestCase {
|
||||
@Mock
|
||||
private ConfigurationDao configDao;
|
||||
|
||||
@Mock
|
||||
private QuotaEmailConfigurationDaoImpl quotaEmailConfigurationDaoMock;
|
||||
|
||||
@Mock
|
||||
private QuotaAccountVO quotaAccountVOMock;
|
||||
|
||||
@ -92,43 +98,142 @@ public class QuotaAlertManagerImplTest extends TestCase {
|
||||
|
||||
@Before
|
||||
public void setup() throws IllegalAccessException, NoSuchFieldException, ConfigurationException {
|
||||
TransactionLegacy.open("QuotaAlertManagerImplTest");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCheckAndSendQuotaAlertEmails() {
|
||||
AccountVO accountVO = new AccountVO();
|
||||
accountVO.setId(2L);
|
||||
accountVO.setDomainId(1L);
|
||||
accountVO.setType(Account.Type.NORMAL);
|
||||
Mockito.when(accountDao.findById(Mockito.anyLong())).thenReturn(accountVO);
|
||||
|
||||
QuotaAccountVO acc = new QuotaAccountVO(2L);
|
||||
acc.setQuotaBalance(new BigDecimal(404));
|
||||
acc.setQuotaMinBalance(new BigDecimal(100));
|
||||
acc.setQuotaBalanceDate(new Date());
|
||||
acc.setQuotaAlertDate(null);
|
||||
acc.setQuotaEnforce(0);
|
||||
List<QuotaAccountVO> accounts = new ArrayList<>();
|
||||
accounts.add(acc);
|
||||
Mockito.when(quotaAcc.listAllQuotaAccount()).thenReturn(accounts);
|
||||
Mockito.doReturn(new BigDecimal(404)).when(quotaAccountVOMock).getQuotaBalance();
|
||||
Mockito.doReturn(new BigDecimal(100)).when(quotaAccountVOMock).getQuotaMinBalance();
|
||||
Mockito.doReturn(balanceDateMock).when(quotaAccountVOMock).getQuotaBalanceDate();
|
||||
Mockito.doReturn(null).when(quotaAccountVOMock).getQuotaAlertDate();
|
||||
Mockito.doReturn(0).when(quotaAccountVOMock).getQuotaEnforce();
|
||||
|
||||
// Don't test sendQuotaAlert yet
|
||||
Mockito.doNothing().when(quotaAlertManager).sendQuotaAlert(Mockito.any(QuotaAlertManagerImpl.DeferredQuotaEmail.class));
|
||||
Mockito.lenient().doReturn(true).when(quotaAlertManager).lockAccount(Mockito.anyLong());
|
||||
TransactionLegacy.open("QuotaAlertManagerImplTest");
|
||||
}
|
||||
|
||||
// call real method on send monthly statement
|
||||
Mockito.doCallRealMethod().when(quotaAlertManager).checkAndSendQuotaAlertEmails();
|
||||
@Test
|
||||
public void isQuotaEmailTypeEnabledForAccountTestConfigurationIsEnabledAndEmailIsConfiguredReturnConfiguredValue() {
|
||||
boolean expectedValue = !QuotaConfig.QuotaEnableEmails.value();
|
||||
QuotaEmailConfigurationVO quotaEmailConfigurationVoMock = Mockito.mock(QuotaEmailConfigurationVO.class);
|
||||
Mockito.when(quotaEmailConfigurationVoMock.isEnabled()).thenReturn(expectedValue);
|
||||
Mockito.doReturn(quotaEmailConfigurationVoMock).when(quotaEmailConfigurationDaoMock).findByAccountIdAndEmailTemplateType(Mockito.anyLong(), Mockito.any(QuotaConfig.QuotaEmailTemplateTypes.class));
|
||||
|
||||
// Case1: valid balance, no email should be sent
|
||||
quotaAlertManager.checkAndSendQuotaAlertEmails();
|
||||
Mockito.verify(quotaAlertManager, Mockito.times(0)).sendQuotaAlert(Mockito.any(QuotaAlertManagerImpl.DeferredQuotaEmail.class));
|
||||
boolean result = quotaAlertManager.isQuotaEmailTypeEnabledForAccount(accountMock, QuotaConfig.QuotaEmailTemplateTypes.QUOTA_EMPTY);
|
||||
|
||||
// Case2: low balance, email should be sent
|
||||
accounts.get(0).setQuotaBalance(new BigDecimal(99));
|
||||
//Mockito.when(quotaAcc.listAll()).thenReturn(accounts);
|
||||
quotaAlertManager.checkAndSendQuotaAlertEmails();
|
||||
Mockito.verify(quotaAlertManager, Mockito.times(1)).sendQuotaAlert(Mockito.any(QuotaAlertManagerImpl.DeferredQuotaEmail.class));
|
||||
Assert.assertEquals(expectedValue, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void isQuotaEmailTypeEnabledForAccountTestConfigurationIsEnabledAndEmailIsNotConfiguredReturnDefaultValue() {
|
||||
boolean defaultValue = QuotaConfig.QuotaEnableEmails.value();
|
||||
|
||||
boolean result = quotaAlertManager.isQuotaEmailTypeEnabledForAccount(accountMock, QuotaConfig.QuotaEmailTemplateTypes.QUOTA_EMPTY);
|
||||
|
||||
Assert.assertEquals(defaultValue, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkQuotaAlertEmailForAccountTestNullAccountBalance() {
|
||||
Mockito.doReturn(null).when(quotaAccountVOMock).getQuotaBalance();
|
||||
quotaAlertManager.checkQuotaAlertEmailForAccount(deferredQuotaEmailListMock, quotaAccountVOMock);
|
||||
Mockito.verify(accountDao, Mockito.never()).findById(Mockito.any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkQuotaAlertEmailForAccountTestNullAccount() {
|
||||
Mockito.doReturn(new BigDecimal(1)).when(quotaAccountVOMock).getQuotaBalance();
|
||||
Mockito.doReturn(null).when(accountDao).findById(Mockito.any());
|
||||
quotaAlertManager.checkQuotaAlertEmailForAccount(deferredQuotaEmailListMock, quotaAccountVOMock);
|
||||
Mockito.verify(quotaAccountVOMock, Mockito.never()).getQuotaBalanceDate();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkQuotaAlertEmailForAccountTestEnoughBalance() {
|
||||
quotaAlertManager.checkQuotaAlertEmailForAccount(deferredQuotaEmailListMock, quotaAccountVOMock);
|
||||
Mockito.verify(quotaAlertManager, Mockito.never()).lockAccount(Mockito.anyLong());
|
||||
Mockito.verify(deferredQuotaEmailListMock, Mockito.never()).add(Mockito.any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkQuotaAlertEmailForAccountTestBalanceLowerThanZeroAndLockAccountEnforcementFalse() {
|
||||
Mockito.doReturn(new BigDecimal(-1)).when(quotaAccountVOMock).getQuotaBalance();
|
||||
|
||||
quotaAlertManager._lockAccountEnforcement = false;
|
||||
Mockito.doReturn(1).when(quotaAccountVOMock).getQuotaEnforce();
|
||||
quotaAlertManager.checkQuotaAlertEmailForAccount(deferredQuotaEmailListMock, quotaAccountVOMock);
|
||||
Mockito.verify(quotaAlertManager, Mockito.never()).lockAccount(Mockito.anyLong());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkQuotaAlertEmailForAccountTestBalanceLowerThanZeroAndLockableFalse() {
|
||||
Mockito.doReturn(new BigDecimal(-1)).when(quotaAccountVOMock).getQuotaBalance();
|
||||
|
||||
quotaAlertManager._lockAccountEnforcement = true;
|
||||
Mockito.doReturn(1).when(quotaAccountVOMock).getQuotaEnforce();
|
||||
Mockito.doReturn(false).when(quotaManagerMock).isLockable(Mockito.any());
|
||||
quotaAlertManager.checkQuotaAlertEmailForAccount(deferredQuotaEmailListMock, quotaAccountVOMock);
|
||||
Mockito.verify(quotaAlertManager, Mockito.never()).lockAccount(Mockito.anyLong());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkQuotaAlertEmailForAccountTestBalanceLowerThanZeroAndIsLockableFalse() {
|
||||
Mockito.doReturn(new BigDecimal(-1)).when(quotaAccountVOMock).getQuotaBalance();
|
||||
|
||||
quotaAlertManager._lockAccountEnforcement = true;
|
||||
Mockito.doReturn(1).when(quotaAccountVOMock).getQuotaEnforce();
|
||||
Mockito.doReturn(false).when(quotaManagerMock).isLockable(Mockito.any());
|
||||
quotaAlertManager.checkQuotaAlertEmailForAccount(deferredQuotaEmailListMock, quotaAccountVOMock);
|
||||
Mockito.verify(quotaAlertManager, Mockito.never()).lockAccount(Mockito.anyLong());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkQuotaAlertEmailForAccountTestBalanceLowerThanZeroAndLockAccount() {
|
||||
Mockito.doReturn(new BigDecimal(-1)).when(quotaAccountVOMock).getQuotaBalance();
|
||||
|
||||
quotaAlertManager._lockAccountEnforcement = true;
|
||||
Mockito.doReturn(1).when(quotaAccountVOMock).getQuotaEnforce();
|
||||
Mockito.doReturn(true).when(quotaManagerMock).isLockable(Mockito.any());
|
||||
quotaAlertManager.checkQuotaAlertEmailForAccount(deferredQuotaEmailListMock, quotaAccountVOMock);
|
||||
Mockito.verify(quotaAlertManager).lockAccount(Mockito.anyLong());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkQuotaAlertEmailForAccountTestBalanceLowerThanZeroAndAlertDateNotNullAndBalanceDateNotAfter() {
|
||||
Mockito.doReturn(new Date()).when(quotaAccountVOMock).getQuotaAlertDate();
|
||||
Mockito.doReturn(new BigDecimal(-1)).when(quotaAccountVOMock).getQuotaBalance();
|
||||
Mockito.doReturn(false).when(balanceDateMock).after(Mockito.any());
|
||||
|
||||
quotaAlertManager.checkQuotaAlertEmailForAccount(deferredQuotaEmailListMock, quotaAccountVOMock);
|
||||
Mockito.verify(deferredQuotaEmailListMock, Mockito.never()).add(Mockito.any());
|
||||
}
|
||||
|
||||
public void checkQuotaAlertEmailForAccountTestBalanceLowerThanZeroAndAlertDateNotNullAndGetDifferenceDaysSmallerThanOne() {
|
||||
Mockito.doReturn(new Date()).when(quotaAccountVOMock).getQuotaAlertDate();
|
||||
Mockito.doReturn(new BigDecimal(-1)).when(quotaAccountVOMock).getQuotaBalance();
|
||||
Mockito.doReturn(true).when(balanceDateMock).after(Mockito.any());
|
||||
Mockito.doReturn(0L).when(quotaAlertManager).getDifferenceDays(Mockito.any(), Mockito.any());
|
||||
|
||||
quotaAlertManager.checkQuotaAlertEmailForAccount(deferredQuotaEmailListMock, quotaAccountVOMock);
|
||||
Mockito.verify(deferredQuotaEmailListMock, Mockito.never()).add(Mockito.any());
|
||||
}
|
||||
|
||||
public void checkQuotaAlertEmailForAccountTestBalanceLowerThanZeroAndAlertDateNotNullAndBalanceAfterAndDifferenceBiggerThanOne() {
|
||||
Mockito.doReturn(new Date()).when(quotaAccountVOMock).getQuotaAlertDate();
|
||||
Mockito.doReturn(new BigDecimal(-1)).when(quotaAccountVOMock).getQuotaBalance();
|
||||
Mockito.doReturn(true).when(balanceDateMock).after(Mockito.any());
|
||||
Mockito.doReturn(2).when(quotaAlertManager).getDifferenceDays(Mockito.any(), Mockito.any());
|
||||
|
||||
quotaAlertManager.checkQuotaAlertEmailForAccount(deferredQuotaEmailListMock, quotaAccountVOMock);
|
||||
Mockito.verify(deferredQuotaEmailListMock).add(Mockito.any());
|
||||
}
|
||||
|
||||
public void checkQuotaAlertEmailForAccountTestBalanceLowerThanZeroAndAlertDateNull() {
|
||||
Mockito.doReturn(new BigDecimal(-1)).when(quotaAccountVOMock).getQuotaBalance();
|
||||
|
||||
quotaAlertManager.checkQuotaAlertEmailForAccount(deferredQuotaEmailListMock, quotaAccountVOMock);
|
||||
Mockito.verify(deferredQuotaEmailListMock).add(Mockito.any());
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -196,12 +301,12 @@ public class QuotaAlertManagerImplTest extends TestCase {
|
||||
@Test
|
||||
public void testGetDifferenceDays() {
|
||||
Date now = new Date();
|
||||
assertTrue(QuotaAlertManagerImpl.getDifferenceDays(now, now) == 0L);
|
||||
assertTrue(quotaAlertManager.getDifferenceDays(now, now) == 0L);
|
||||
Calendar c = Calendar.getInstance();
|
||||
c.setTimeZone(TimeZone.getTimeZone("UTC"));
|
||||
Calendar c2 = (Calendar)c.clone();
|
||||
c2.add(Calendar.DATE, 1);
|
||||
assertEquals(1L, QuotaAlertManagerImpl.getDifferenceDays(c.getTime(), c2.getTime()));
|
||||
assertEquals(1L, quotaAlertManager.getDifferenceDays(c.getTime(), c2.getTime()));
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@ -16,7 +16,6 @@
|
||||
// under the License.
|
||||
package org.apache.cloudstack.quota;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.ArrayList;
|
||||
@ -24,17 +23,21 @@ import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import javax.mail.MessagingException;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import org.apache.cloudstack.framework.config.dao.ConfigurationDao;
|
||||
import org.apache.cloudstack.quota.QuotaStatementImpl.QuotaStatementPeriods;
|
||||
import org.apache.cloudstack.quota.constant.QuotaConfig;
|
||||
import org.apache.cloudstack.quota.dao.QuotaAccountDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaEmailConfigurationDaoImpl;
|
||||
import org.apache.cloudstack.quota.dao.QuotaEmailTemplatesDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaUsageDao;
|
||||
import org.apache.cloudstack.quota.vo.QuotaAccountVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaEmailTemplatesVO;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.InjectMocks;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.Spy;
|
||||
@ -60,7 +63,20 @@ public class QuotaStatementTest extends TestCase {
|
||||
@Mock
|
||||
QuotaAlertManager alertManager;
|
||||
|
||||
@Mock
|
||||
QuotaEmailConfigurationDaoImpl quotaEmailConfigurationDaoMock;
|
||||
|
||||
@Mock
|
||||
QuotaEmailTemplatesDao quotaEmailTemplatesDaoMock;
|
||||
|
||||
@Mock
|
||||
QuotaEmailTemplatesVO quotaEmailTemplatesVOMock;
|
||||
|
||||
@Mock
|
||||
List<QuotaEmailTemplatesVO> listMock;
|
||||
|
||||
@Spy
|
||||
@InjectMocks
|
||||
QuotaStatementImpl quotaStatement = new QuotaStatementImpl();
|
||||
|
||||
private void injectMockToField(Object mock, String fieldName) throws NoSuchFieldException, IllegalAccessException {
|
||||
@ -227,7 +243,10 @@ public class QuotaStatementTest extends TestCase {
|
||||
|
||||
|
||||
@Test
|
||||
public void testSendStatement() throws UnsupportedEncodingException, MessagingException {
|
||||
public void sendStatementTestUnconfiguredEmail() {
|
||||
boolean defaultConfigurationValue = QuotaConfig.QuotaEnableEmails.value();
|
||||
Mockito.doReturn(defaultConfigurationValue).when(alertManager).isQuotaEmailTypeEnabledForAccount(Mockito.any(AccountVO.class), Mockito.any(QuotaConfig.QuotaEmailTemplateTypes.class));
|
||||
|
||||
Calendar date = Calendar.getInstance();
|
||||
AccountVO accountVO = new AccountVO();
|
||||
accountVO.setId(2L);
|
||||
@ -252,4 +271,46 @@ public class QuotaStatementTest extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sendStatementTestEnabledEmail() {
|
||||
Mockito.doReturn(true).when(alertManager).isQuotaEmailTypeEnabledForAccount(Mockito.any(AccountVO.class), Mockito.any(QuotaConfig.QuotaEmailTemplateTypes.class));
|
||||
|
||||
Calendar date = Calendar.getInstance();
|
||||
AccountVO accountVO = new AccountVO();
|
||||
accountVO.setId(2L);
|
||||
accountVO.setDomainId(1L);
|
||||
Mockito.lenient().when(accountDao.findById(Mockito.anyLong())).thenReturn(accountVO);
|
||||
|
||||
QuotaAccountVO acc = new QuotaAccountVO(2L);
|
||||
acc.setQuotaBalance(new BigDecimal(404));
|
||||
acc.setLastStatementDate(null);
|
||||
List<QuotaAccountVO> accounts = new ArrayList<>();
|
||||
accounts.add(acc);
|
||||
Mockito.lenient().when(quotaAcc.listAllQuotaAccount()).thenReturn(accounts);
|
||||
|
||||
Mockito.lenient().when(quotaUsage.findTotalQuotaUsage(Mockito.anyLong(), Mockito.anyLong(), Mockito.anyInt(), Mockito.any(Date.class), Mockito.any(Date.class)))
|
||||
.thenReturn(new BigDecimal(100));
|
||||
|
||||
// call real method on send monthly statement
|
||||
quotaStatement.sendStatement();
|
||||
Calendar period[] = quotaStatement.statementTime(date, QuotaStatementPeriods.MONTHLY);
|
||||
if (period != null){
|
||||
Mockito.verify(alertManager, Mockito.times(1)).sendQuotaAlert(Mockito.any(QuotaAlertManagerImpl.DeferredQuotaEmail.class));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void sendStatementTestDisabledEmail() {
|
||||
QuotaAccountVO quotaAccountVoMock = Mockito.mock(QuotaAccountVO.class);
|
||||
Mockito.when(quotaAccountVoMock.getQuotaBalance()).thenReturn(BigDecimal.ONE);
|
||||
Mockito.when(quotaAcc.listAllQuotaAccount()).thenReturn(List.of(quotaAccountVoMock));
|
||||
AccountVO accountVoMock = Mockito.mock(AccountVO.class);
|
||||
Mockito.doReturn(accountVoMock).when(accountDao).findById(Mockito.anyLong());
|
||||
Mockito.doReturn(false).when(alertManager).isQuotaEmailTypeEnabledForAccount(Mockito.any(AccountVO.class), Mockito.any(QuotaConfig.QuotaEmailTemplateTypes.class));
|
||||
|
||||
quotaStatement.sendStatement();
|
||||
|
||||
Mockito.verify(quotaStatement, Mockito.never()).statementTime(Mockito.any(), Mockito.any());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -0,0 +1,79 @@
|
||||
//Licensed to the Apache Software Foundation (ASF) under one
|
||||
//or more contributor license agreements. See the NOTICE file
|
||||
//distributed with this work for additional information
|
||||
//regarding copyright ownership. The ASF licenses this file
|
||||
//to you under the Apache License, Version 2.0 (the
|
||||
//"License"); you may not use this file except in compliance
|
||||
//with the License. You may obtain a copy of the License at
|
||||
//
|
||||
//http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
//Unless required by applicable law or agreed to in writing,
|
||||
//software distributed under the License is distributed on an
|
||||
//"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
//KIND, either express or implied. See the License for the
|
||||
//specific language governing permissions and limitations
|
||||
//under the License.
|
||||
package org.apache.cloudstack.api.command;
|
||||
|
||||
import com.cloud.utils.Pair;
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.BaseCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.response.AccountResponse;
|
||||
import org.apache.cloudstack.api.response.QuotaConfigureEmailResponse;
|
||||
import org.apache.cloudstack.api.response.QuotaResponseBuilder;
|
||||
import org.apache.cloudstack.quota.vo.QuotaEmailConfigurationVO;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
@APICommand(name = "quotaConfigureEmail", responseObject = QuotaConfigureEmailResponse.class, description = "Configure a quota email template", since = "4.20.0.0",
|
||||
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
|
||||
public class QuotaConfigureEmailCmd extends BaseCmd {
|
||||
|
||||
@Parameter(name = ApiConstants.ACCOUNT_ID, type = CommandType.UUID, entityType = AccountResponse.class, required = true,
|
||||
description = "Account ID for which to configure quota template email or min balance")
|
||||
private long accountId;
|
||||
|
||||
@Parameter(name = ApiConstants.TEMPLATE_NAME, type = CommandType.STRING, description = "Quota email template name which should be configured")
|
||||
private String templateName;
|
||||
|
||||
@Parameter(name = ApiConstants.ENABLE, type = CommandType.BOOLEAN, description = "If the quota email template should be enabled")
|
||||
private Boolean enable;
|
||||
|
||||
@Parameter(name = "minbalance", type = CommandType.DOUBLE, description = "New quota account min balance")
|
||||
private Double minBalance;
|
||||
|
||||
@Inject
|
||||
private QuotaResponseBuilder responseBuilder;
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
Pair<QuotaEmailConfigurationVO, Double> result = responseBuilder.configureQuotaEmail(this);
|
||||
QuotaConfigureEmailResponse quotaConfigureEmailResponse = responseBuilder.createQuotaConfigureEmailResponse(result.first(), result.second(), accountId);
|
||||
quotaConfigureEmailResponse.setResponseName(getCommandName());
|
||||
this.setResponseObject(quotaConfigureEmailResponse);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
return accountId;
|
||||
}
|
||||
|
||||
public long getAccountId() {
|
||||
return accountId;
|
||||
}
|
||||
|
||||
public String getTemplateName() {
|
||||
return templateName;
|
||||
}
|
||||
|
||||
public Boolean getEnable() {
|
||||
return enable;
|
||||
}
|
||||
|
||||
public Double getMinBalance() {
|
||||
return minBalance;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,54 @@
|
||||
//Licensed to the Apache Software Foundation (ASF) under one
|
||||
//or more contributor license agreements. See the NOTICE file
|
||||
//distributed with this work for additional information
|
||||
//regarding copyright ownership. The ASF licenses this file
|
||||
//to you under the Apache License, Version 2.0 (the
|
||||
//"License"); you may not use this file except in compliance
|
||||
//with the License. You may obtain a copy of the License at
|
||||
//
|
||||
//http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
//Unless required by applicable law or agreed to in writing,
|
||||
//software distributed under the License is distributed on an
|
||||
//"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
//KIND, either express or implied. See the License for the
|
||||
//specific language governing permissions and limitations
|
||||
//under the License.
|
||||
package org.apache.cloudstack.api.command;
|
||||
|
||||
import com.cloud.user.Account;
|
||||
import org.apache.cloudstack.api.APICommand;
|
||||
import org.apache.cloudstack.api.ApiConstants;
|
||||
import org.apache.cloudstack.api.BaseCmd;
|
||||
import org.apache.cloudstack.api.Parameter;
|
||||
import org.apache.cloudstack.api.response.AccountResponse;
|
||||
import org.apache.cloudstack.api.response.ListResponse;
|
||||
import org.apache.cloudstack.api.response.QuotaConfigureEmailResponse;
|
||||
import org.apache.cloudstack.api.response.QuotaResponseBuilder;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
@APICommand(name = "quotaListEmailConfiguration", responseObject = QuotaConfigureEmailResponse.class, description = "List quota email template configurations", since = "4.20.0.0",
|
||||
requestHasSensitiveInfo = false, responseHasSensitiveInfo = false)
|
||||
public class QuotaListEmailConfigurationCmd extends BaseCmd {
|
||||
|
||||
@Parameter(name = ApiConstants.ACCOUNT_ID, type = BaseCmd.CommandType.UUID, entityType = AccountResponse.class, required = true,
|
||||
description = "Account ID for which to list quota template email configurations")
|
||||
private long accountId;
|
||||
|
||||
@Inject
|
||||
private QuotaResponseBuilder responseBuilder;
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
ListResponse<QuotaConfigureEmailResponse> response = new ListResponse<>();
|
||||
response.setResponses(responseBuilder.listEmailConfiguration(accountId));
|
||||
response.setResponseName(getCommandName());
|
||||
setResponseObject(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getEntityOwnerId() {
|
||||
return Account.ACCOUNT_ID_SYSTEM;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,78 @@
|
||||
//Licensed to the Apache Software Foundation (ASF) under one
|
||||
//or more contributor license agreements. See the NOTICE file
|
||||
//distributed with this work for additional information
|
||||
//regarding copyright ownership. The ASF licenses this file
|
||||
//to you under the Apache License, Version 2.0 (the
|
||||
//"License"); you may not use this file except in compliance
|
||||
//with the License. You may obtain a copy of the License at
|
||||
//
|
||||
//http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
//Unless required by applicable law or agreed to in writing,
|
||||
//software distributed under the License is distributed on an
|
||||
//"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
//KIND, either express or implied. See the License for the
|
||||
//specific language governing permissions and limitations
|
||||
//under the License.
|
||||
package org.apache.cloudstack.api.response;
|
||||
|
||||
import com.cloud.serializer.Param;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import org.apache.cloudstack.api.BaseResponse;
|
||||
|
||||
|
||||
public class QuotaConfigureEmailResponse extends BaseResponse {
|
||||
|
||||
@SerializedName("account")
|
||||
@Param(description = "The configured account's id.")
|
||||
private String accountId;
|
||||
|
||||
@SerializedName("templatename")
|
||||
@Param(description = "The template's name.")
|
||||
private String templateName;
|
||||
|
||||
@SerializedName("enabled")
|
||||
@Param(description = "Whether the template is enabled.")
|
||||
private Boolean enabled;
|
||||
|
||||
@SerializedName("minbalance")
|
||||
@Param(description = "The configured account's min balance.")
|
||||
private Double minBalance;
|
||||
|
||||
public QuotaConfigureEmailResponse() {
|
||||
super("quotaconfigureemail");
|
||||
setResponseName("");
|
||||
}
|
||||
|
||||
public String getAccountId() {
|
||||
return accountId;
|
||||
}
|
||||
|
||||
public void setAccountId(String accountId) {
|
||||
this.accountId = accountId;
|
||||
}
|
||||
|
||||
public String getTemplateName() {
|
||||
return templateName;
|
||||
}
|
||||
|
||||
public void setTemplateName(String templateName) {
|
||||
this.templateName = templateName;
|
||||
}
|
||||
|
||||
public Boolean getEnabled() {
|
||||
return enabled;
|
||||
}
|
||||
|
||||
public void setEnabled(Boolean enabled) {
|
||||
this.enabled = enabled;
|
||||
}
|
||||
|
||||
public Double getMinBalance() {
|
||||
return minBalance;
|
||||
}
|
||||
|
||||
public void setMinBalance(Double minBalance) {
|
||||
this.minBalance = minBalance;
|
||||
}
|
||||
}
|
||||
@ -17,6 +17,7 @@
|
||||
package org.apache.cloudstack.api.response;
|
||||
|
||||
import org.apache.cloudstack.api.command.QuotaBalanceCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaConfigureEmailCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaEmailTemplateListCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaEmailTemplateUpdateCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaStatementCmd;
|
||||
@ -24,6 +25,7 @@ import org.apache.cloudstack.api.command.QuotaTariffCreateCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaTariffListCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaTariffUpdateCmd;
|
||||
import org.apache.cloudstack.quota.vo.QuotaBalanceVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaEmailConfigurationVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaTariffVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaUsageVO;
|
||||
|
||||
@ -69,4 +71,10 @@ public interface QuotaResponseBuilder {
|
||||
QuotaTariffVO createQuotaTariff(QuotaTariffCreateCmd cmd);
|
||||
|
||||
boolean deleteQuotaTariff(String quotaTariffUuid);
|
||||
|
||||
Pair<QuotaEmailConfigurationVO, Double> configureQuotaEmail(QuotaConfigureEmailCmd cmd);
|
||||
|
||||
QuotaConfigureEmailResponse createQuotaConfigureEmailResponse(QuotaEmailConfigurationVO quotaEmailConfigurationVO, Double minBalance, long accountId);
|
||||
|
||||
List<QuotaConfigureEmailResponse> listEmailConfiguration(long accountId);
|
||||
}
|
||||
|
||||
@ -38,6 +38,7 @@ import com.cloud.utils.DateUtil;
|
||||
import org.apache.cloudstack.api.ApiErrorCode;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.command.QuotaBalanceCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaConfigureEmailCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaEmailTemplateListCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaEmailTemplateUpdateCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaStatementCmd;
|
||||
@ -54,12 +55,14 @@ import org.apache.cloudstack.quota.constant.QuotaTypes;
|
||||
import org.apache.cloudstack.quota.dao.QuotaAccountDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaBalanceDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaCreditsDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaEmailConfigurationDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaEmailTemplatesDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaTariffDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaUsageDao;
|
||||
import org.apache.cloudstack.quota.vo.QuotaAccountVO;
|
||||
import org.apache.cloudstack.quota.dao.QuotaUsageDao;
|
||||
import org.apache.cloudstack.quota.vo.QuotaBalanceVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaCreditsVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaEmailConfigurationVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaEmailTemplatesVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaTariffVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaUsageVO;
|
||||
@ -104,7 +107,7 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder {
|
||||
@Inject
|
||||
private AccountDao _accountDao;
|
||||
@Inject
|
||||
private QuotaAccountDao _quotaAccountDao;
|
||||
private QuotaAccountDao quotaAccountDao;
|
||||
@Inject
|
||||
private DomainDao _domainDao;
|
||||
@Inject
|
||||
@ -113,6 +116,8 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder {
|
||||
private QuotaStatement _statement;
|
||||
@Inject
|
||||
private QuotaManager _quotaManager;
|
||||
@Inject
|
||||
private QuotaEmailConfigurationDao quotaEmailConfigurationDao;
|
||||
|
||||
@Override
|
||||
public QuotaTariffResponse createQuotaTariffResponse(QuotaTariffVO tariff) {
|
||||
@ -165,7 +170,7 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder {
|
||||
result.add(qr);
|
||||
}
|
||||
} else {
|
||||
Pair<List<QuotaAccountVO>, Integer> data = _quotaAccountDao.listAllQuotaAccount(startIndex, pageSize);
|
||||
Pair<List<QuotaAccountVO>, Integer> data = quotaAccountDao.listAllQuotaAccount(startIndex, pageSize);
|
||||
count = data.second();
|
||||
for (final QuotaAccountVO quotaAccount : data.first()) {
|
||||
AccountVO account = _accountDao.findById(quotaAccount.getId());
|
||||
@ -676,4 +681,99 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder {
|
||||
|
||||
return _quotaTariffDao.updateQuotaTariff(quotaTariff);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Pair<QuotaEmailConfigurationVO, Double> configureQuotaEmail(QuotaConfigureEmailCmd cmd) {
|
||||
validateQuotaConfigureEmailCmdParameters(cmd);
|
||||
|
||||
Double minBalance = cmd.getMinBalance();
|
||||
|
||||
if (minBalance != null) {
|
||||
_quotaService.setMinBalance(cmd.getAccountId(), cmd.getMinBalance());
|
||||
}
|
||||
|
||||
QuotaEmailConfigurationVO configurationVO = getQuotaEmailConfigurationVo(cmd);
|
||||
return new Pair<>(configurationVO, minBalance);
|
||||
}
|
||||
|
||||
protected QuotaEmailConfigurationVO getQuotaEmailConfigurationVo(QuotaConfigureEmailCmd cmd) {
|
||||
if (cmd.getTemplateName() == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<QuotaEmailTemplatesVO> templateVO = _quotaEmailTemplateDao.listAllQuotaEmailTemplates(cmd.getTemplateName());
|
||||
if (templateVO.isEmpty()) {
|
||||
throw new InvalidParameterValueException(String.format("Could not find template with name [%s].", cmd.getTemplateName()));
|
||||
}
|
||||
long templateId = templateVO.get(0).getId();
|
||||
QuotaEmailConfigurationVO configurationVO = quotaEmailConfigurationDao.findByAccountIdAndEmailTemplateId(cmd.getAccountId(), templateId);
|
||||
|
||||
if (configurationVO == null) {
|
||||
configurationVO = new QuotaEmailConfigurationVO(cmd.getAccountId(), templateId, cmd.getEnable());
|
||||
quotaEmailConfigurationDao.persistQuotaEmailConfiguration(configurationVO);
|
||||
return configurationVO;
|
||||
}
|
||||
|
||||
configurationVO.setEnabled(cmd.getEnable());
|
||||
return quotaEmailConfigurationDao.updateQuotaEmailConfiguration(configurationVO);
|
||||
}
|
||||
|
||||
protected void validateQuotaConfigureEmailCmdParameters(QuotaConfigureEmailCmd cmd) {
|
||||
if (quotaAccountDao.findByIdQuotaAccount(cmd.getAccountId()) == null) {
|
||||
throw new InvalidParameterValueException("You must have the quota enabled for this account to configure quota emails.");
|
||||
}
|
||||
|
||||
if (cmd.getTemplateName() == null && cmd.getMinBalance() == null) {
|
||||
throw new InvalidParameterValueException("You should inform at least the 'minbalance' or both the 'templatename' and 'enable' parameters.");
|
||||
}
|
||||
|
||||
if ((cmd.getTemplateName() != null && cmd.getEnable() == null) || (cmd.getTemplateName() == null && cmd.getEnable() != null)) {
|
||||
throw new InvalidParameterValueException("Parameter 'enable' must be informed along with 'templatename'.");
|
||||
}
|
||||
}
|
||||
|
||||
public QuotaConfigureEmailResponse createQuotaConfigureEmailResponse(QuotaEmailConfigurationVO quotaEmailConfigurationVO, Double minBalance, long accountId) {
|
||||
QuotaConfigureEmailResponse quotaConfigureEmailResponse = new QuotaConfigureEmailResponse();
|
||||
|
||||
Account account = _accountDao.findByIdIncludingRemoved(accountId);
|
||||
if (quotaEmailConfigurationVO != null) {
|
||||
QuotaEmailTemplatesVO templateVO = _quotaEmailTemplateDao.findById(quotaEmailConfigurationVO.getEmailTemplateId());
|
||||
|
||||
quotaConfigureEmailResponse.setAccountId(account.getUuid());
|
||||
quotaConfigureEmailResponse.setTemplateName(templateVO.getTemplateName());
|
||||
quotaConfigureEmailResponse.setEnabled(quotaEmailConfigurationVO.isEnabled());
|
||||
}
|
||||
|
||||
quotaConfigureEmailResponse.setMinBalance(minBalance);
|
||||
|
||||
return quotaConfigureEmailResponse;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<QuotaConfigureEmailResponse> listEmailConfiguration(long accountId) {
|
||||
List<QuotaEmailConfigurationVO> emailConfigurationVOList = quotaEmailConfigurationDao.listByAccount(accountId);
|
||||
Account account = _accountDao.findById(accountId);
|
||||
QuotaAccountVO quotaAccountVO = quotaAccountDao.findByIdQuotaAccount(accountId);
|
||||
|
||||
List<QuotaConfigureEmailResponse> quotaConfigureEmailResponseList = new ArrayList<>();
|
||||
for (QuotaEmailConfigurationVO quotaEmailConfigurationVO : emailConfigurationVOList) {
|
||||
quotaConfigureEmailResponseList.add(createQuotaConfigureEmailResponse(quotaEmailConfigurationVO, account, quotaAccountVO));
|
||||
}
|
||||
|
||||
return quotaConfigureEmailResponseList;
|
||||
}
|
||||
|
||||
protected QuotaConfigureEmailResponse createQuotaConfigureEmailResponse(QuotaEmailConfigurationVO quotaEmailConfigurationVO, Account account, QuotaAccountVO quotaAccountVO) {
|
||||
QuotaConfigureEmailResponse quotaConfigureEmailResponse = new QuotaConfigureEmailResponse();
|
||||
|
||||
QuotaEmailTemplatesVO templateVO = _quotaEmailTemplateDao.findById(quotaEmailConfigurationVO.getEmailTemplateId());
|
||||
|
||||
quotaConfigureEmailResponse.setAccountId(account.getUuid());
|
||||
quotaConfigureEmailResponse.setTemplateName(templateVO.getTemplateName());
|
||||
quotaConfigureEmailResponse.setEnabled(quotaEmailConfigurationVO.isEnabled());
|
||||
|
||||
quotaConfigureEmailResponse.setMinBalance(quotaAccountVO.getQuotaMinBalance().doubleValue());
|
||||
|
||||
return quotaConfigureEmailResponse;
|
||||
}
|
||||
}
|
||||
|
||||
@ -28,10 +28,12 @@ import javax.inject.Inject;
|
||||
import javax.naming.ConfigurationException;
|
||||
|
||||
import org.apache.cloudstack.api.command.QuotaBalanceCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaConfigureEmailCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaCreditsCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaEmailTemplateListCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaEmailTemplateUpdateCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaEnabledCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaListEmailConfigurationCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaStatementCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaSummaryCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaTariffCreateCmd;
|
||||
@ -116,6 +118,8 @@ public class QuotaServiceImpl extends ManagerBase implements QuotaService, Confi
|
||||
cmdList.add(QuotaEmailTemplateUpdateCmd.class);
|
||||
cmdList.add(QuotaTariffCreateCmd.class);
|
||||
cmdList.add(QuotaTariffDeleteCmd.class);
|
||||
cmdList.add(QuotaConfigureEmailCmd.class);
|
||||
cmdList.add(QuotaListEmailConfigurationCmd.class);
|
||||
return cmdList;
|
||||
}
|
||||
|
||||
@ -128,7 +132,7 @@ public class QuotaServiceImpl extends ManagerBase implements QuotaService, Confi
|
||||
public ConfigKey<?>[] getConfigKeys() {
|
||||
return new ConfigKey<?>[] {QuotaPluginEnabled, QuotaEnableEnforcement, QuotaCurrencySymbol, QuotaCurrencyLocale, QuotaStatementPeriod, QuotaSmtpHost, QuotaSmtpPort, QuotaSmtpTimeout,
|
||||
QuotaSmtpUser, QuotaSmtpPassword, QuotaSmtpAuthType, QuotaSmtpSender, QuotaSmtpEnabledSecurityProtocols, QuotaSmtpUseStartTLS, QuotaActivationRuleTimeout, QuotaAccountEnabled,
|
||||
QuotaEmailHeader, QuotaEmailFooter};
|
||||
QuotaEmailHeader, QuotaEmailFooter, QuotaEnableEmails};
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@ -30,6 +30,7 @@ import java.util.function.Consumer;
|
||||
import com.cloud.domain.DomainVO;
|
||||
import com.cloud.domain.dao.DomainDao;
|
||||
import org.apache.cloudstack.api.ServerApiException;
|
||||
import org.apache.cloudstack.api.command.QuotaConfigureEmailCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaEmailTemplateListCmd;
|
||||
import org.apache.cloudstack.api.command.QuotaEmailTemplateUpdateCmd;
|
||||
import org.apache.cloudstack.framework.config.ConfigKey;
|
||||
@ -37,13 +38,17 @@ import org.apache.cloudstack.quota.QuotaService;
|
||||
import org.apache.cloudstack.quota.QuotaStatement;
|
||||
import org.apache.cloudstack.quota.constant.QuotaConfig;
|
||||
import org.apache.cloudstack.quota.constant.QuotaTypes;
|
||||
import org.apache.cloudstack.quota.dao.QuotaAccountDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaBalanceDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaCreditsDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaEmailConfigurationDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaEmailTemplatesDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaTariffDao;
|
||||
import org.apache.cloudstack.quota.dao.QuotaUsageDao;
|
||||
import org.apache.cloudstack.quota.vo.QuotaAccountVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaBalanceVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaCreditsVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaEmailConfigurationVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaEmailTemplatesVO;
|
||||
import org.apache.cloudstack.quota.vo.QuotaTariffVO;
|
||||
import org.apache.commons.lang3.time.DateUtils;
|
||||
@ -103,6 +108,12 @@ public class QuotaResponseBuilderImplTest extends TestCase {
|
||||
@Mock
|
||||
QuotaUsageDao quotaUsageDaoMock;
|
||||
|
||||
@Mock
|
||||
QuotaAccountDao quotaAccountDaoMock;
|
||||
|
||||
@Mock
|
||||
QuotaEmailConfigurationDao quotaEmailConfigurationDaoMock;
|
||||
|
||||
@InjectMocks
|
||||
QuotaResponseBuilderImpl quotaResponseBuilderSpy = Mockito.spy(QuotaResponseBuilderImpl.class);
|
||||
|
||||
@ -114,6 +125,15 @@ public class QuotaResponseBuilderImplTest extends TestCase {
|
||||
@Mock
|
||||
DomainVO domainVOMock;
|
||||
|
||||
@Mock
|
||||
QuotaConfigureEmailCmd quotaConfigureEmailCmdMock;
|
||||
|
||||
@Mock
|
||||
QuotaAccountVO quotaAccountVOMock;
|
||||
|
||||
@Mock
|
||||
QuotaEmailTemplatesVO quotaEmailTemplatesVoMock;
|
||||
|
||||
private void overrideDefaultQuotaEnabledConfigValue(final Object value) throws IllegalAccessException, NoSuchFieldException {
|
||||
Field f = ConfigKey.class.getDeclaredField("_defaultValue");
|
||||
f.setAccessible(true);
|
||||
@ -403,4 +423,96 @@ public class QuotaResponseBuilderImplTest extends TestCase {
|
||||
|
||||
assertTrue(quotaSummaryResponse.getQuotaEnabled());
|
||||
}
|
||||
|
||||
|
||||
@Test (expected = InvalidParameterValueException.class)
|
||||
public void validateQuotaConfigureEmailCmdParametersTestNullQuotaAccount() {
|
||||
Mockito.doReturn(null).when(quotaAccountDaoMock).findByIdQuotaAccount(Mockito.any());
|
||||
quotaResponseBuilderSpy.validateQuotaConfigureEmailCmdParameters(quotaConfigureEmailCmdMock);
|
||||
}
|
||||
|
||||
@Test (expected = InvalidParameterValueException.class)
|
||||
public void validateQuotaConfigureEmailCmdParametersTestNullTemplateNameAndMinBalance() {
|
||||
Mockito.doReturn(quotaAccountVOMock).when(quotaAccountDaoMock).findByIdQuotaAccount(Mockito.any());
|
||||
Mockito.doReturn(null).when(quotaConfigureEmailCmdMock).getTemplateName();
|
||||
Mockito.doReturn(null).when(quotaConfigureEmailCmdMock).getMinBalance();
|
||||
quotaResponseBuilderSpy.validateQuotaConfigureEmailCmdParameters(quotaConfigureEmailCmdMock);
|
||||
}
|
||||
|
||||
@Test (expected = InvalidParameterValueException.class)
|
||||
public void validateQuotaConfigureEmailCmdParametersTestEnableNullAndTemplateNameNotNull() {
|
||||
Mockito.doReturn(quotaAccountVOMock).when(quotaAccountDaoMock).findByIdQuotaAccount(Mockito.any());
|
||||
Mockito.doReturn(QuotaConfig.QuotaEmailTemplateTypes.QUOTA_LOW.toString()).when(quotaConfigureEmailCmdMock).getTemplateName();
|
||||
Mockito.doReturn(null).when(quotaConfigureEmailCmdMock).getEnable();
|
||||
quotaResponseBuilderSpy.validateQuotaConfigureEmailCmdParameters(quotaConfigureEmailCmdMock);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void validateQuotaConfigureEmailCmdParametersTestNullTemplateName() {
|
||||
Mockito.doReturn(quotaAccountVOMock).when(quotaAccountDaoMock).findByIdQuotaAccount(Mockito.any());
|
||||
Mockito.doReturn(null).when(quotaConfigureEmailCmdMock).getTemplateName();
|
||||
Mockito.doReturn(null).when(quotaConfigureEmailCmdMock).getEnable();
|
||||
Mockito.doReturn(100D).when(quotaConfigureEmailCmdMock).getMinBalance();
|
||||
quotaResponseBuilderSpy.validateQuotaConfigureEmailCmdParameters(quotaConfigureEmailCmdMock);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validateQuotaConfigureEmailCmdParametersTestWithTemplateNameAndEnable() {
|
||||
Mockito.doReturn(quotaAccountVOMock).when(quotaAccountDaoMock).findByIdQuotaAccount(Mockito.any());
|
||||
Mockito.doReturn(QuotaConfig.QuotaEmailTemplateTypes.QUOTA_LOW.toString()).when(quotaConfigureEmailCmdMock).getTemplateName();
|
||||
Mockito.doReturn(true).when(quotaConfigureEmailCmdMock).getEnable();
|
||||
quotaResponseBuilderSpy.validateQuotaConfigureEmailCmdParameters(quotaConfigureEmailCmdMock);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getQuotaEmailConfigurationVoTestTemplateNameIsNull() {
|
||||
Mockito.doReturn(null).when(quotaConfigureEmailCmdMock).getTemplateName();
|
||||
|
||||
QuotaEmailConfigurationVO result = quotaResponseBuilderSpy.getQuotaEmailConfigurationVo(quotaConfigureEmailCmdMock);
|
||||
|
||||
Assert.assertNull(result);
|
||||
}
|
||||
|
||||
@Test (expected = InvalidParameterValueException.class)
|
||||
public void getQuotaEmailConfigurationVoTestNoTemplateFound() {
|
||||
Mockito.doReturn("name").when(quotaConfigureEmailCmdMock).getTemplateName();
|
||||
Mockito.doReturn(new ArrayList<QuotaEmailTemplatesVO>()).when(quotaEmailTemplateDaoMock).listAllQuotaEmailTemplates(Mockito.any());
|
||||
|
||||
quotaResponseBuilderSpy.getQuotaEmailConfigurationVo(quotaConfigureEmailCmdMock);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getQuotaEmailConfigurationVoTestNewConfiguration() {
|
||||
Mockito.doReturn("name").when(quotaConfigureEmailCmdMock).getTemplateName();
|
||||
List<QuotaEmailTemplatesVO> templatesVOArrayList = List.of(quotaEmailTemplatesVoMock);
|
||||
Mockito.doReturn(templatesVOArrayList).when(quotaEmailTemplateDaoMock).listAllQuotaEmailTemplates(Mockito.any());
|
||||
Mockito.doReturn(null).when(quotaEmailConfigurationDaoMock).findByAccountIdAndEmailTemplateId(Mockito.anyLong(), Mockito.anyLong());
|
||||
|
||||
QuotaEmailConfigurationVO result = quotaResponseBuilderSpy.getQuotaEmailConfigurationVo(quotaConfigureEmailCmdMock);
|
||||
|
||||
Mockito.verify(quotaEmailConfigurationDaoMock).persistQuotaEmailConfiguration(Mockito.any());
|
||||
assertEquals(0, result.getAccountId());
|
||||
assertEquals(0, result.getEmailTemplateId());
|
||||
assertFalse(result.isEnabled());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getQuotaEmailConfigurationVoTestExistingConfiguration() {
|
||||
Mockito.doReturn("name").when(quotaConfigureEmailCmdMock).getTemplateName();
|
||||
List<QuotaEmailTemplatesVO> templatesVOArrayList = List.of(quotaEmailTemplatesVoMock);
|
||||
Mockito.doReturn(templatesVOArrayList).when(quotaEmailTemplateDaoMock).listAllQuotaEmailTemplates(Mockito.any());
|
||||
|
||||
QuotaEmailConfigurationVO quotaEmailConfigurationVO = new QuotaEmailConfigurationVO(1, 2, true);
|
||||
Mockito.doReturn(quotaEmailConfigurationVO).when(quotaEmailConfigurationDaoMock).findByAccountIdAndEmailTemplateId(Mockito.anyLong(), Mockito.anyLong());
|
||||
Mockito.doReturn(quotaEmailConfigurationVO).when(quotaEmailConfigurationDaoMock).updateQuotaEmailConfiguration(Mockito.any());
|
||||
|
||||
QuotaEmailConfigurationVO result = quotaResponseBuilderSpy.getQuotaEmailConfigurationVo(quotaConfigureEmailCmdMock);
|
||||
|
||||
Mockito.verify(quotaEmailConfigurationDaoMock).updateQuotaEmailConfiguration(Mockito.any());
|
||||
|
||||
assertEquals(1, result.getAccountId());
|
||||
assertEquals(2, result.getEmailTemplateId());
|
||||
assertFalse(result.isEnabled());
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user