diff --git a/client/tomcatconf/commands.properties.in b/client/tomcatconf/commands.properties.in index d7a97aaccc4..fe8f632bfd3 100644 --- a/client/tomcatconf/commands.properties.in +++ b/client/tomcatconf/commands.properties.in @@ -786,7 +786,7 @@ addGloboDnsHost=1 ### Quota Service quotaStatement=15 quotaBalance=15 -quotaSummary=1 +quotaSummary=15 quotaUpdate=1 quotaTariffList=15 quotaTariffUpdate=1 diff --git a/plugins/database/quota/src/org/apache/cloudstack/api/command/QuotaBalanceCmd.java b/plugins/database/quota/src/org/apache/cloudstack/api/command/QuotaBalanceCmd.java index 6f471e0293b..eb15a11913d 100644 --- a/plugins/database/quota/src/org/apache/cloudstack/api/command/QuotaBalanceCmd.java +++ b/plugins/database/quota/src/org/apache/cloudstack/api/command/QuotaBalanceCmd.java @@ -30,12 +30,9 @@ import org.apache.cloudstack.api.response.AccountResponse; import org.apache.cloudstack.api.response.DomainResponse; import org.apache.cloudstack.api.response.QuotaBalanceResponse; import org.apache.cloudstack.api.response.QuotaResponseBuilder; -import org.apache.cloudstack.context.CallContext; import org.apache.cloudstack.quota.vo.QuotaBalanceVO; import org.apache.cloudstack.api.response.QuotaStatementItemResponse; -import com.cloud.user.Account; - @APICommand(name = "quotaBalance", responseObject = QuotaStatementItemResponse.class, description = "Create a quota balance statement", since = "4.6.0", requestHasSensitiveInfo = false, responseHasSensitiveInfo = false) public class QuotaBalanceCmd extends BaseCmd { @@ -43,10 +40,10 @@ public class QuotaBalanceCmd extends BaseCmd { private static final String s_name = "quotabalanceresponse"; - @Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, required = true, description = "Optional, Account Id for which statement needs to be generated") + @Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, required = true, description = "Account Id for which statement needs to be generated") private String accountName; - @Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, required = true, entityType = DomainResponse.class, description = "Optional, If domain Id is given and the caller is domain admin then the statement is generated for domain.") + @Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, required = true, entityType = DomainResponse.class, description = "If domain Id is given and the caller is domain admin then the statement is generated for domain.") private Long domainId; @Parameter(name = ApiConstants.END_DATE, type = CommandType.DATE, description = "End date range for quota query. Use yyyy-MM-dd as the date format, e.g. startDate=2009-06-03.") @@ -108,11 +105,7 @@ public class QuotaBalanceCmd extends BaseCmd { @Override public long getEntityOwnerId() { - Long accountId = _accountService.getActiveAccountByName(accountName, domainId).getAccountId(); - if (accountId == null) { - return CallContext.current().getCallingAccount().getId(); - } - return Account.ACCOUNT_ID_SYSTEM; + return _accountService.getActiveAccountByName(accountName, domainId).getAccountId(); } @Override diff --git a/plugins/database/quota/src/org/apache/cloudstack/api/command/QuotaSummaryCmd.java b/plugins/database/quota/src/org/apache/cloudstack/api/command/QuotaSummaryCmd.java index aaf35e7f81d..aaa6c1c588a 100644 --- a/plugins/database/quota/src/org/apache/cloudstack/api/command/QuotaSummaryCmd.java +++ b/plugins/database/quota/src/org/apache/cloudstack/api/command/QuotaSummaryCmd.java @@ -19,10 +19,14 @@ 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.BaseListCmd; +import org.apache.cloudstack.api.Parameter; +import org.apache.cloudstack.api.response.DomainResponse; import org.apache.cloudstack.api.response.ListResponse; import org.apache.cloudstack.api.response.QuotaResponseBuilder; import org.apache.cloudstack.api.response.QuotaSummaryResponse; +import org.apache.cloudstack.context.CallContext; import org.apache.log4j.Logger; import java.util.List; @@ -34,6 +38,12 @@ public class QuotaSummaryCmd extends BaseListCmd { public static final Logger s_logger = Logger.getLogger(QuotaSummaryCmd.class); private static final String s_name = "quotasummaryresponse"; + @Parameter(name = ApiConstants.ACCOUNT, type = CommandType.STRING, required = false, description = "Optional, Account Id for which statement needs to be generated") + private String accountName; + + @Parameter(name = ApiConstants.DOMAIN_ID, type = CommandType.UUID, required = false, entityType = DomainResponse.class, description = "Optional, If domain Id is given and the caller is domain admin then the statement is generated for domain.") + private Long domainId; + @Inject QuotaResponseBuilder _responseBuilder; @@ -43,14 +53,38 @@ public class QuotaSummaryCmd extends BaseListCmd { @Override public void execute() { - - List responses = _responseBuilder.createQuotaSummaryResponse(); + Account caller = CallContext.current().getCallingAccount(); + List responses; + if (caller.getAccountId() == 2) { //non root admin + if (getAccountName() != null && getDomainId() != null) + responses = _responseBuilder.createQuotaSummaryResponse(caller.getAccountName(), caller.getDomainId()); + else + responses = _responseBuilder.createQuotaSummaryResponse(); + } else { + responses = _responseBuilder.createQuotaSummaryResponse(caller.getAccountName(), caller.getDomainId()); + } final ListResponse response = new ListResponse(); response.setResponses(responses); response.setResponseName(getCommandName()); setResponseObject(response); } + public String getAccountName() { + return accountName; + } + + public void setAccountName(String accountName) { + this.accountName = accountName; + } + + public Long getDomainId() { + return domainId; + } + + public void setDomainId(Long domainId) { + this.domainId = domainId; + } + @Override public String getCommandName() { return s_name; diff --git a/plugins/database/quota/src/org/apache/cloudstack/api/response/QuotaResponseBuilder.java b/plugins/database/quota/src/org/apache/cloudstack/api/response/QuotaResponseBuilder.java index 576ab2b45b2..3ec735e0839 100644 --- a/plugins/database/quota/src/org/apache/cloudstack/api/response/QuotaResponseBuilder.java +++ b/plugins/database/quota/src/org/apache/cloudstack/api/response/QuotaResponseBuilder.java @@ -43,6 +43,8 @@ public interface QuotaResponseBuilder { List createQuotaSummaryResponse(); + List createQuotaSummaryResponse(String accountName, Long domainId); + QuotaBalanceResponse createQuotaLastBalanceResponse(List quotaBalance, Date startDate); QuotaCreditsResponse addQuotaCredits(Long accountId, Long domainId, Double amount, Long updatedBy, Date despositedOn); diff --git a/plugins/database/quota/src/org/apache/cloudstack/api/response/QuotaResponseBuilderImpl.java b/plugins/database/quota/src/org/apache/cloudstack/api/response/QuotaResponseBuilderImpl.java index b62a6901362..44c9d6bdb9c 100644 --- a/plugins/database/quota/src/org/apache/cloudstack/api/response/QuotaResponseBuilderImpl.java +++ b/plugins/database/quota/src/org/apache/cloudstack/api/response/QuotaResponseBuilderImpl.java @@ -35,13 +35,11 @@ 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.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.QuotaEmailTemplatesVO; @@ -94,8 +92,6 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder { @Inject private RegionManager _regionMgr; @Inject - private QuotaAccountDao _quotaAcc; - @Inject private QuotaStatement _statement; @Override @@ -112,14 +108,42 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder { return response; } + @Override + public List createQuotaSummaryResponse(final String accountName, final Long domainId) { + List result = new ArrayList(); + Calendar[] period = _statement.getCurrentStatementTime(); + + if (accountName != null && domainId != null) { + Account account = _accountDao.findActiveAccount(accountName, domainId); + QuotaSummaryResponse qr = new QuotaSummaryResponse(); + DomainVO domain = _domainDao.findById(account.getDomainId()); + BigDecimal curBalance = _quotaBalanceDao.lastQuotaBalance(account.getAccountId(), account.getDomainId(), period[1].getTime()); + BigDecimal quotaUsage = _quotaUsageDao.findTotalQuotaUsage(account.getAccountId(), account.getDomainId(), null, period[0].getTime(), period[1].getTime()); + + qr.setAccountId(account.getAccountId()); + qr.setAccountName(account.getAccountName()); + qr.setDomainId(account.getDomainId()); + qr.setDomainName(domain.getName()); + qr.setBalance(curBalance); + qr.setQuotaUsage(quotaUsage); + qr.setState(account.getState()); + qr.setStartDate(period[0].getTime()); + qr.setEndDate(period[1].getTime()); + qr.setCurrency(QuotaConfig.QuotaCurrencySymbol.value()); + qr.setObjectName("summary"); + result.add(qr); + } + + return result; + } + @Override public List createQuotaSummaryResponse() { List result = new ArrayList(); Calendar[] period = _statement.getCurrentStatementTime(); - for (final QuotaAccountVO quotaAccount : _quotaAcc.listAllQuotaAccount()) { + for (final AccountVO account : _accountDao.listAll()) { QuotaSummaryResponse qr = new QuotaSummaryResponse(); - AccountVO account = _accountDao.findById(quotaAccount.getId()); DomainVO domain = _domainDao.findById(account.getDomainId()); BigDecimal curBalance = _quotaBalanceDao.lastQuotaBalance(account.getAccountId(), account.getDomainId(), period[1].getTime()); BigDecimal quotaUsage = _quotaUsageDao.findTotalQuotaUsage(account.getAccountId(), account.getDomainId(), null, period[0].getTime(), period[1].getTime()); @@ -187,6 +211,8 @@ public class QuotaResponseBuilderImpl implements QuotaResponseBuilder { resp.setEndDate(endDate); resp.setEndQuota(new BigDecimal(0).add(lastCredits)); } else { + resp.setStartDate(startDate); + resp.setEndDate(endDate); resp.setStartQuota(new BigDecimal(0)); resp.setEndQuota(new BigDecimal(0)); } diff --git a/plugins/database/quota/src/org/apache/cloudstack/quota/QuotaServiceImpl.java b/plugins/database/quota/src/org/apache/cloudstack/quota/QuotaServiceImpl.java index 03237db3db4..1b4c98f6997 100644 --- a/plugins/database/quota/src/org/apache/cloudstack/quota/QuotaServiceImpl.java +++ b/plugins/database/quota/src/org/apache/cloudstack/quota/QuotaServiceImpl.java @@ -198,7 +198,8 @@ public class QuotaServiceImpl extends ManagerBase implements QuotaService, Confi s_logger.debug("getQuotaBalance3: Found records size=" + qbrecords.size()); } if (qbrecords.isEmpty()) { - throw new InvalidParameterValueException("Incorrect Date range there are no quota records between these dates start date " + adjustedStartDate + " and end date:" + endDate); + s_logger.info("There are no quota records between these dates start date " + adjustedStartDate + " and end date:" + endDate); + return qbrecords; } else { return qbrecords; } diff --git a/ui/plugins/quota/quota.js b/ui/plugins/quota/quota.js index be1a41a3360..281a5221ec2 100644 --- a/ui/plugins/quota/quota.js +++ b/ui/plugins/quota/quota.js @@ -31,7 +31,10 @@ sectionSelect: { label: 'label.select-view', preFilter: function(args) { - return ['summary', 'tariff', 'emailTemplates']; + if (isAdmin()) + return ['summary', 'tariffEdit', 'emailTemplates']; + else + return ['summary', 'tariffView']; } }, sections: { @@ -40,6 +43,7 @@ title: 'label.quota.summary', listView: { label: 'label.quota.summary', + disableInfiniteScrolling: true, fields: { account: { label: 'label.account', @@ -128,9 +132,9 @@ label: 'label.quota.statement.balance' }], actions: { - add: { label: 'label.quota.add.credits', + preFilter: function(args) { return isAdmin(); }, messages: { confirm: function(args) { return 'label.quota.add.credits'; @@ -187,12 +191,6 @@ $(window).trigger('cloudStack.fullRefresh'); } }, - - - - - - }, tabs: { details: { @@ -279,7 +277,6 @@ enddate: { label: 'label.quota.enddate', isDatepicker: true, - minDate: '#startdate', maxDate: '+0d', validation: { required: true @@ -341,7 +338,9 @@ }); }, error:function(data) { - args.response.error(parseXMLHttpResponse(data)); + cloudStack.dialog.notice({ + message: parseXMLHttpResponse(data) + }); } }); } @@ -387,7 +386,6 @@ enddate: { label: 'label.quota.enddate', isDatepicker: true, - dependsOn: 'startdate', maxDate: '+0d', validation: { required: true @@ -453,7 +451,9 @@ }); }, error:function(data) { - args.response.error(parseXMLHttpResponse(data)); + cloudStack.dialog.notice({ + message: parseXMLHttpResponse(data) + }); } }); } @@ -462,7 +462,7 @@ - tariff: { + tariffEdit: { type: 'select', title: 'label.quota.tariff', listView: { @@ -472,64 +472,67 @@ edit: { label: 'label.change.value', action: function(args) { - var data = { - usagetype: args.data.jsonObj.usageType, - }; - var tariffVal = args.data.tariffValue.split(' '); - if (tariffVal.length==2){ - data.value = tariffVal[1]; - } - else { - data.value = tariffVal[0]; - } - if (!isNaN(parseFloat(data.value)) && isFinite(data.value)){ - var updateTariffForm = cloudStack.dialog.createForm({ - form: { - title: 'label.quota.configuration', - fields: { - tariffValue: { - label: 'label.quota.value', - number: true, - validation: { - required: true - } - }, - effectiveDate: { - label: 'label.quota.tariff.effectivedate', - isDatepicker: true, - dependsOn: 'startdate', - minDate: '+1d', - validation: { - required: true - } - }, - } - }, - after: function(argsLocal) { - data.startDate = argsLocal.data.effectiveDate; - data.value = argsLocal.data.tariffValue; - $.ajax({ - url: createURL('quotaTariffUpdate'), - data: data, - type: "POST", - success: function(json) { - // Refresh listings on chosen date to reflect new tariff - $($.find('div.search-bar input')).val(data.startDate); - $('#basic_search').click(); + console.log("isAdmin "+ isAdmin()); + if (isAdmin()){ + var data = { + usagetype: args.data.jsonObj.usageType, + }; + var tariffVal = args.data.tariffValue.split(' '); + if (tariffVal.length==2){ + data.value = tariffVal[1]; + } + else { + data.value = tariffVal[0]; + } + if (!isNaN(parseFloat(data.value)) && isFinite(data.value)){ + var updateTariffForm = cloudStack.dialog.createForm({ + form: { + title: 'label.quota.configuration', + fields: { + tariffValue: { + label: 'label.quota.value', + number: true, + validation: { + required: true + } + }, + effectiveDate: { + label: 'label.quota.tariff.effectivedate', + isDatepicker: true, + dependsOn: 'startdate', + minDate: '+1d', + validation: { + required: true + } + }, } - }); - } - }); - updateTariffForm.find('input[name=tariffValue]').val(data.value); - updateTariffForm.find('input[name=effectiveDate]').focus(); - } - else { - alert("Bad tariff value, this should be a number " + data.value); - $(window).trigger('cloudStack.fullRefresh'); - }//bad data.value - NaN - } - } - }, + }, + after: function(argsLocal) { + data.startDate = argsLocal.data.effectiveDate; + data.value = argsLocal.data.tariffValue; + $.ajax({ + url: createURL('quotaTariffUpdate'), + data: data, + type: "POST", + success: function(json) { + // Refresh listings on chosen date to reflect new tariff + $($.find('div.search-bar input')).val(data.startDate); + $('#basic_search').click(); + } + }); + } + }); + updateTariffForm.find('input[name=tariffValue]').val(data.value); + updateTariffForm.find('input[name=effectiveDate]').focus(); + } + else { + alert("Bad tariff value, this should be a number " + data.value); + $(window).trigger('cloudStack.fullRefresh'); + }//bad data.value - NaN + } // if is ADMIN + } // end action + }//edits + },//actions fields: { usageName: { label: 'label.usage.type', @@ -585,6 +588,68 @@ } } }, + + + tariffView: { + type: 'select', + title: 'label.quota.tariff', + listView: { + label: 'label.quota.tariff', + disableInfiniteScrolling: true, + fields: { + usageName: { + label: 'label.usage.type', + id: true, + truncate: true + }, + usageUnit: { + label: 'label.usage.unit' + }, + tariffValue: { + label: 'label.quota.tariff.value', + }, + description: { + label: 'label.quota.description', + truncate: true + } + }, + dataProvider: function(args) { + var data = {}; + if (args.filterBy.search.value) { + data.startdate = args.filterBy.search.value; + } + $.ajax({ + url: createURL('quotaTariffList'), + data: data, + dataType: "json", + async: true, + success: function(json) { + var items = json.quotatarifflistresponse.quotatariff; + $.each(items, function(idx, item) { + items[idx].tariffValue = items[idx].currency + ' ' + items[idx].tariffValue; + }); + args.response.success({ + data: items + }); + + // Hook up date picker + var input = $($.find('div.search-bar input')); + input.datepicker({ + defaultDate: new Date(), + changeMonth: true, + dateFormat: "yy-mm-dd", + }); + input.parent().attr('title', _l('label.quota.effectivedate')); + }, + error: function(data) { + cloudStack.dialog.notice({ + message: parseXMLHttpResponse(data) + }); + } + }); + } + } + }, emailTemplates: { type: 'select',