diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/DeviceList.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/DeviceList.java index 5adb83af039..8c6c4945c4c 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/DeviceList.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/beans/DeviceList.java @@ -29,6 +29,15 @@ public class DeviceList extends BasePaginatedResult { private List devices = new ArrayList<>(); + @ApiModelProperty(name = "totalCost", value = "Total cost of all devices per tenant", required = false) + private double totalCost; + + @ApiModelProperty(name = "message", value = "Send information text to the billing UI", required = false) + private String message; + + @ApiModelProperty(name = "billedDateIsValid", value = "Check if user entered date is valid", required = false) + private boolean billedDateIsValid; + @ApiModelProperty(value = "List of devices returned") @JsonProperty("devices") public List getList() { @@ -39,6 +48,30 @@ public class DeviceList extends BasePaginatedResult { this.devices = devices; } + public boolean isBilledDateIsValid() { + return billedDateIsValid; + } + + public void setBilledDateIsValid(boolean billedDateIsValid) { + this.billedDateIsValid = billedDateIsValid; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public double getTotalCost() { + return totalCost; + } + + public void setTotalCost(double totalCost) { + this.totalCost = totalCost; + } + @Override public String toString() { StringBuilder sb = new StringBuilder(); diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/DeviceManagementService.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/DeviceManagementService.java index d5d52446944..e2d88ea046a 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/DeviceManagementService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/api/DeviceManagementService.java @@ -81,6 +81,7 @@ import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; +import java.sql.Timestamp; import java.util.List; /** @@ -343,6 +344,171 @@ public interface DeviceManagementService { @QueryParam("limit") int limit); + + @GET + @Path("/billing") + @Produces(MediaType.APPLICATION_JSON) + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = "GET", + value = "Getting Cost details of devices in a tenant", + notes = "Provides individual cost and total cost of all devices per tenant.", + tags = "Device Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:devices:view") + }) + } + ) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "OK. \n Successfully fetched the list of devices.", + response = DeviceList.class, + responseHeaders = { + @ResponseHeader( + name = "Content-Type", + description = "The content type of the body"), + @ResponseHeader( + name = "ETag", + description = "Entity Tag of the response resource.\n" + + "Used by caches, or in conditional requests."), + @ResponseHeader( + name = "Last-Modified", + description = "Date and time the resource was last modified.\n" + + "Used by caches, or in conditional requests."), + }), + @ApiResponse( + code = 304, + message = "Not Modified. \n Empty body because the client already has the latest version of " + + "the requested resource.\n"), + @ApiResponse( + code = 400, + message = "The incoming request has more than one selection criteria defined via the query parameters.", + response = ErrorResponse.class), + @ApiResponse( + code = 404, + message = "The search criteria did not match any device registered with the server.", + response = ErrorResponse.class), + @ApiResponse( + code = 406, + message = "Not Acceptable.\n The requested media type is not supported."), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Server error occurred while fetching the device list.", + response = ErrorResponse.class) + }) + Response getDevicesBilling( + @ApiParam( + name = "tenantDomain", + value = "The tenant domain.", + required = false) + String tenantDomain, + @ApiParam( + name = "startDate", + value = "The start date.", + required = false) + Timestamp startDate, + @ApiParam( + name = "endDate", + value = "The end date.", + required = false) + Timestamp endDate, + @ApiParam( + name = "generateBill", + value = "The generate bill boolean.", + required = false) + boolean generateBill, + @ApiParam( + name = "offset", + value = "The starting pagination index for the complete list of qualified items.", + required = false, + defaultValue = "0") + @QueryParam("offset") + int offset, + @ApiParam( + name = "limit", + value = "Provide how many device details you require from the starting pagination index/offset.", + required = false, + defaultValue = "10") + @QueryParam("limit") + int limit); + + + @GET + @Path("/billing/file") + @Produces(MediaType.APPLICATION_JSON) + @ApiOperation( + produces = MediaType.APPLICATION_JSON, + httpMethod = "GET", + value = "Getting Cost details of devices in a tenant", + notes = "Provides individual cost and total cost of all devices per tenant.", + tags = "Device Management", + extensions = { + @Extension(properties = { + @ExtensionProperty(name = Constants.SCOPE, value = "perm:devices:view") + }) + } + ) + @ApiResponses(value = { + @ApiResponse(code = 200, message = "OK. \n Successfully fetched the list of devices.", + response = DeviceList.class, + responseHeaders = { + @ResponseHeader( + name = "Content-Type", + description = "The content type of the body"), + @ResponseHeader( + name = "Content-Disposition", + description = "The content disposition of the body"), + @ResponseHeader( + name = "ETag", + description = "Entity Tag of the response resource.\n" + + "Used by caches, or in conditional requests."), + @ResponseHeader( + name = "Last-Modified", + description = "Date and time the resource was last modified.\n" + + "Used by caches, or in conditional requests."), + }), + @ApiResponse( + code = 304, + message = "Not Modified. \n Empty body because the client already has the latest version of " + + "the requested resource.\n"), + @ApiResponse( + code = 400, + message = "The incoming request has more than one selection criteria defined via the query parameters.", + response = ErrorResponse.class), + @ApiResponse( + code = 404, + message = "The search criteria did not match any device registered with the server.", + response = ErrorResponse.class), + @ApiResponse( + code = 406, + message = "Not Acceptable.\n The requested media type is not supported."), + @ApiResponse( + code = 500, + message = "Internal Server Error. \n Server error occurred while fetching the device list.", + response = ErrorResponse.class) + }) + Response exportBilling( + @ApiParam( + name = "tenantDomain", + value = "The tenant domain.", + required = false) + String tenantDomain, + @ApiParam( + name = "startDate", + value = "The start date.", + required = false) + Timestamp startDate, + @ApiParam( + name = "endDate", + value = "The end date.", + required = false) + Timestamp endDate, + @ApiParam( + name = "generateBill", + value = "The generate bill boolean.", + required = false) + boolean generateBill); + @GET @Produces(MediaType.APPLICATION_JSON) @ApiOperation( diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/DeviceManagementServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/DeviceManagementServiceImpl.java index ca9df6cb88e..6e6882cfb85 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/DeviceManagementServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.api/src/main/java/org/wso2/carbon/device/mgt/jaxrs/service/impl/DeviceManagementServiceImpl.java @@ -119,26 +119,17 @@ import org.wso2.carbon.identity.jwt.client.extension.service.JWTClientManagerSer import org.wso2.carbon.policy.mgt.common.PolicyManagementException; import org.wso2.carbon.policy.mgt.core.PolicyManagerService; import org.wso2.carbon.user.api.UserStoreException; +import org.wso2.carbon.user.core.service.RealmService; import org.wso2.carbon.utils.multitenancy.MultitenantUtils; import javax.validation.Valid; import javax.validation.constraints.Size; -import javax.ws.rs.DELETE; -import javax.ws.rs.GET; -import javax.ws.rs.HeaderParam; -import javax.ws.rs.POST; -import javax.ws.rs.PUT; -import javax.ws.rs.Path; -import javax.ws.rs.PathParam; -import javax.ws.rs.QueryParam; -import javax.ws.rs.DefaultValue; +import javax.ws.rs.*; import javax.ws.rs.core.Response; +import java.sql.Timestamp; import java.text.ParseException; import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.List; -import java.util.ArrayList; -import java.util.Properties; +import java.util.*; @Path("/devices") public class DeviceManagementServiceImpl implements DeviceManagementService { @@ -214,8 +205,8 @@ public class DeviceManagementServiceImpl implements DeviceManagementService { } if (status != null && !status.isEmpty()) { boolean isStatusEmpty = true; - for (String statusString : status){ - if (StringUtils.isNotBlank(statusString)){ + for (String statusString : status) { + if (StringUtils.isNotBlank(statusString)) { isStatusEmpty = false; break; } @@ -341,6 +332,105 @@ public class DeviceManagementServiceImpl implements DeviceManagementService { } } + @GET + @Override + @Path("/billing") + public Response getDevicesBilling( + @QueryParam("tenantDomain") String tenantDomain, + @QueryParam("startDate") Timestamp startDate, + @QueryParam("endDate") Timestamp endDate, + @QueryParam("generateBill") boolean generateBill, + @QueryParam("offset") int offset, + @DefaultValue("10") + @QueryParam("limit") int limit) { + try { + RequestValidationUtil.validatePaginationParameters(offset, limit); + DeviceManagementProviderService dms = DeviceMgtAPIUtils.getDeviceManagementService(); + PaginationRequest request = new PaginationRequest(offset, limit); + PaginationResult result; + DeviceList devices = new DeviceList(); + int tenantId = 0; + RealmService realmService = DeviceMgtAPIUtils.getRealmService(); + + if (!tenantDomain.isEmpty()) { + tenantId = realmService.getTenantManager().getTenantId(tenantDomain); + } else { + tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId(); + } + + try { + result = dms.getAllDevicesBillings(request, tenantId, tenantDomain, startDate, endDate, generateBill); + } catch (Exception exception) { + String msg = "Error occurred when trying to retrieve billing data"; + log.error(msg, exception); + return Response.serverError().entity( + new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build(); + } + + int resultCount = result.getRecordsTotal(); + if (resultCount == 0) { + Response.status(Response.Status.OK).entity(devices).build(); + } + + devices.setList((List) result.getData()); + devices.setBilledDateIsValid(result.isBilledDateIsValid()); + devices.setMessage(result.getMessage()); + devices.setCount(result.getRecordsTotal()); + devices.setTotalCost(result.getTotalCost()); + return Response.status(Response.Status.OK).entity(devices).build(); + } catch (Exception e) { + String msg = "Error occurred while retrieving billing data"; + log.error(msg, e); + return Response.serverError().entity( + new ErrorResponse.ErrorResponseBuilder().setMessage(msg).build()).build(); + } + } + + @GET + @Override + @Path("/billing/file") + public Response exportBilling( + @QueryParam("tenantDomain") String tenantDomain, + @QueryParam("startDate") Timestamp startDate, + @QueryParam("endDate") Timestamp endDate, + @QueryParam("generateBill") boolean generateBill) { + + try { + DeviceManagementProviderService dms = DeviceMgtAPIUtils.getDeviceManagementService(); + PaginationResult result; + int tenantId = 0; + RealmService realmService = DeviceMgtAPIUtils.getRealmService(); + DeviceList devices = new DeviceList(); + + if (!tenantDomain.isEmpty()) { + tenantId = realmService.getTenantManager().getTenantId(tenantDomain); + } else { + tenantId = CarbonContext.getThreadLocalCarbonContext().getTenantId(); + } + + try { + result = dms.createBillingFile(tenantId, tenantDomain, startDate, endDate, generateBill); + + } catch (Exception exception) { + String msg = "Error occurred when trying to retrieve billing data without pagination"; + log.error(msg, exception); + return null; + } + + devices.setList((List) result.getData()); + devices.setBilledDateIsValid(result.isBilledDateIsValid()); + devices.setMessage(result.getMessage()); + devices.setCount(result.getRecordsTotal()); + devices.setTotalCost(result.getTotalCost()); + return Response.status(Response.Status.OK).entity(devices).build(); + } catch (Exception e) { + String msg = "Error occurred while retrieving billing data without pagination"; + log.error(msg, e); + return null; + } + + } + @GET @Override @Path("/user-devices") @@ -377,8 +467,8 @@ public class DeviceManagementServiceImpl implements DeviceManagementService { * Validate group Id and group Id greater than 0 and exist. * * @param groupId Group ID of the group - * @param from time to start getting DeviceLocationHistorySnapshotWrapper in milliseconds - * @param to time to end getting DeviceLocationHistorySnapshotWrapper in milliseconds + * @param from time to start getting DeviceLocationHistorySnapshotWrapper in milliseconds + * @param to time to end getting DeviceLocationHistorySnapshotWrapper in milliseconds */ private static void validateGroupId(int groupId, long from, long to) throws GroupManagementException, BadRequestException { if (from == 0 || to == 0) { @@ -407,7 +497,7 @@ public class DeviceManagementServiceImpl implements DeviceManagementService { @QueryParam("to") long to, @QueryParam("type") String type, @DefaultValue("0") @QueryParam("offset") int offset, - @DefaultValue("100") @QueryParam("limit") int limit){ + @DefaultValue("100") @QueryParam("limit") int limit) { try { RequestValidationUtil.validatePaginationParameters(offset, limit); DeviceManagementProviderService dms = DeviceMgtAPIUtils.getDeviceManagementService(); @@ -416,31 +506,31 @@ public class DeviceManagementServiceImpl implements DeviceManagementService { // this is the user who initiates the request String authorizedUser = CarbonContext.getThreadLocalCarbonContext().getUsername(); - try { - validateGroupId(groupId, from, to); - boolean isPermitted = DeviceMgtAPIUtils.checkPermission(groupId, authorizedUser); - if (isPermitted) { - request.setGroupId(groupId); - } else { - String msg = "Current user '" + authorizedUser - + "' doesn't have enough privileges to list devices of group '" - + groupId + "'"; - log.error(msg); - return Response.status(Response.Status.FORBIDDEN).entity(msg).build(); - } - } catch (GroupManagementException e) { - String msg = "Error occurred while getting the data using '" + groupId + "'"; - log.error(msg); - return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); - } catch (UserStoreException e){ - String msg = "Error occurred while retrieving role list of user '" + authorizedUser + "'"; + try { + validateGroupId(groupId, from, to); + boolean isPermitted = DeviceMgtAPIUtils.checkPermission(groupId, authorizedUser); + if (isPermitted) { + request.setGroupId(groupId); + } else { + String msg = "Current user '" + authorizedUser + + "' doesn't have enough privileges to list devices of group '" + + groupId + "'"; log.error(msg); - return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); + return Response.status(Response.Status.FORBIDDEN).entity(msg).build(); } + } catch (GroupManagementException e) { + String msg = "Error occurred while getting the data using '" + groupId + "'"; + log.error(msg); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); + } catch (UserStoreException e) { + String msg = "Error occurred while retrieving role list of user '" + authorizedUser + "'"; + log.error(msg); + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); + } PaginationResult result = dms.getAllDevices(request, false); - if(!result.getData().isEmpty()){ + if (!result.getData().isEmpty()) { devices.setList((List) result.getData()); for (Device device : devices.getList()) { @@ -548,7 +638,7 @@ public class DeviceManagementServiceImpl implements DeviceManagementService { DeviceData deviceData = new DeviceData(); deviceData.setDeviceIdentifier(deviceIdentifier); - if (!StringUtils.isBlank(ifModifiedSince)){ + if (!StringUtils.isBlank(ifModifiedSince)) { SimpleDateFormat format = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z"); try { sinceDate = format.parse(ifModifiedSince); @@ -561,10 +651,10 @@ public class DeviceManagementServiceImpl implements DeviceManagementService { } } - if (!StringUtils.isBlank(owner)){ + if (!StringUtils.isBlank(owner)) { deviceData.setDeviceOwner(owner); } - if (!StringUtils.isBlank(ownership)){ + if (!StringUtils.isBlank(ownership)) { deviceData.setDeviceOwnership(ownership); } device = dms.getDevice(deviceData, true); @@ -654,7 +744,7 @@ public class DeviceManagementServiceImpl implements DeviceManagementService { sinceDate = format.parse(ifModifiedSince); } catch (ParseException e) { String message = "Error occurred while parse the since date.Invalid date string is provided in " + - "'If-Modified-Since' header"; + "'If-Modified-Since' header"; log.error(message, e); return Response.status(Response.Status.BAD_REQUEST).entity( new ErrorResponse.ErrorResponseBuilder().setMessage("Invalid date " + @@ -667,7 +757,7 @@ public class DeviceManagementServiceImpl implements DeviceManagementService { String message = "No device is modified after the timestamp provided in 'If-Modified-Since' header"; log.error(message); return Response.status(Response.Status.NOT_MODIFIED).entity("No device is modified " + - "after the timestamp provided in 'If-Modified-Since' header").build(); + "after the timestamp provided in 'If-Modified-Since' header").build(); } } else { device = dms.getDevice(id, requireDeviceInfo); @@ -682,7 +772,7 @@ public class DeviceManagementServiceImpl implements DeviceManagementService { // check whether the user is authorized if (!deviceAccessAuthorizationService.isUserAuthorized(deviceIdentifier, authorizedUser)) { String message = "User '" + authorizedUser + "' is not authorized to retrieve the given " + - "device id '" + id + "'"; + "device id '" + id + "'"; log.error(message); return Response.status(Response.Status.UNAUTHORIZED).entity( new ErrorResponse.ErrorResponseBuilder().setCode(401l).setMessage(message).build()).build(); @@ -837,7 +927,7 @@ public class DeviceManagementServiceImpl implements DeviceManagementService { List devices; DeviceList deviceList = new DeviceList(); try { - if(map.getProperties().isEmpty()){ + if (map.getProperties().isEmpty()) { if (log.isDebugEnabled()) { log.debug("No search criteria defined when querying devices."); } @@ -845,7 +935,7 @@ public class DeviceManagementServiceImpl implements DeviceManagementService { } DeviceManagementProviderService dms = DeviceMgtAPIUtils.getDeviceManagementService(); devices = dms.getDevicesBasedOnProperties(map.getProperties()); - if(devices == null || devices.isEmpty()){ + if (devices == null || devices.isEmpty()) { if (log.isDebugEnabled()) { log.debug("No Devices Found for criteria : " + map); } @@ -1145,14 +1235,14 @@ public class DeviceManagementServiceImpl implements DeviceManagementService { /** * List device status history * - * @param type Device type - * @param id Device id + * @param type Device type + * @param id Device id * @return {@link Response} object */ @GET @Path("/{type}/{id}/getstatushistory") public Response getDeviceStatusHistory(@PathParam("type") @Size(max = 45) String type, - @PathParam("id") @Size(max = 45) String id) { + @PathParam("id") @Size(max = 45) String id) { //TODO check authorization for this RequestValidationUtil.validateDeviceIdentifier(type, id); DeviceManagementProviderService deviceManagementProviderService = @@ -1177,14 +1267,14 @@ public class DeviceManagementServiceImpl implements DeviceManagementService { /** * List device status history for the current enrolment * - * @param type Device type - * @param id Device id + * @param type Device type + * @param id Device id * @return {@link Response} object */ @GET @Path("/{type}/{id}/getenrolmentstatushistory") public Response getCurrentEnrolmentDeviceStatusHistory(@PathParam("type") @Size(max = 45) String type, - @PathParam("id") @Size(max = 45) String id) { + @PathParam("id") @Size(max = 45) String id) { //TODO check authorization for this or current enrolment should be based on for the enrolment associated with the user RequestValidationUtil.validateDeviceIdentifier(type, id); DeviceManagementProviderService deviceManagementProviderService = @@ -1488,7 +1578,7 @@ public class DeviceManagementServiceImpl implements DeviceManagementService { if (MDMAppConstants.AndroidConstants.OPCODE_INSTALL_APPLICATION.equals(operation.getCode()) || MDMAppConstants.AndroidConstants.OPCODE_UNINSTALL_APPLICATION.equals(operation.getCode())) { ApplicationManager applicationManager = DeviceMgtAPIUtils.getApplicationManager(); - applicationManager.updateSubsStatus(device.getId(), operation.getId(),operation.getStatus().toString()); + applicationManager.updateSubsStatus(device.getId(), operation.getId(), operation.getStatus().toString()); } return Response.status(Response.Status.OK).entity("OperationStatus updated successfully.").build(); } catch (BadRequestException e) { @@ -1507,7 +1597,8 @@ public class DeviceManagementServiceImpl implements DeviceManagementService { String msg = "Error occurred when updating the application subscription status of the operation. " + "The device identifier is: " + deviceIdentifier; log.error(msg, e); - return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); } + return Response.status(Response.Status.INTERNAL_SERVER_ERROR).entity(msg).build(); + } } @GET diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/Billing.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/Billing.java new file mode 100644 index 00000000000..79f398a5f80 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/Billing.java @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. 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.wso2.carbon.device.mgt.common; + +import com.google.gson.Gson; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import java.io.Serializable; + +@ApiModel(value = "Billing", description = "This class carries all information related to a device billing.") +public class Billing implements Serializable { + + private static final long serialVersionUID = 1998101711L; + + @ApiModelProperty(name = "invoiceId", value = "ID of the billing.", + required = false) + private int invoiceId; + + @ApiModelProperty(name = "deviceId", value = "Device id of the billing.", + required = false) + private int deviceId; + + @ApiModelProperty(name = "tenantId", value = "Tenant of the device.", + required = false) + private int tenantId; + + @ApiModelProperty(name = "billingStart", value = "Start date of the billing period.", required = false) + private Long billingStart; + + @ApiModelProperty(name = "billingEnd", value = "End date of the billing period.", required = false) + private Long billingEnd; + + @ApiModelProperty(name = "deviceCount", value = "Device count for a billing period", + required = false) + private int deviceCount; + + + public Billing() { + } + + public Billing(int invoiceId, int deviceId, int tenantId, Long billingStart, Long billingEnd) { + this.invoiceId = invoiceId; + this.deviceId = deviceId; + this.tenantId = tenantId; + this.billingStart = billingStart; + this.billingEnd = billingEnd; + } + + public int getInvoiceId() { + return invoiceId; + } + + public void setInvoiceId(int invoiceId) { + this.invoiceId = invoiceId; + } + + public int getDeviceId() { + return deviceId; + } + + public void setDeviceId(int deviceId) { + this.deviceId = deviceId; + } + + public int getTenantId() { + return tenantId; + } + + public void setTenantId(int tenantId) { + this.tenantId = tenantId; + } + + public Long getBillingStart() { + return billingStart; + } + + public void setBillingStart(Long billingStart) { + this.billingStart = billingStart; + } + + public Long getBillingEnd() { + return billingEnd; + } + + public void setBillingEnd(Long billingEnd) { + this.billingEnd = billingEnd; + } + + public int getDeviceCount() { + return deviceCount; + } + + public void setDeviceCount(int deviceCount) { + this.deviceCount = deviceCount; + } + + @Override + public String toString() { + return new Gson().toJson(this); + } + + +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/Device.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/Device.java index df86fd3575e..840d155d440 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/Device.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/Device.java @@ -24,8 +24,10 @@ import com.fasterxml.jackson.annotation.JsonProperty; import org.wso2.carbon.device.mgt.common.app.mgt.Application; import org.wso2.carbon.device.mgt.common.device.details.DeviceInfo; import org.wso2.carbon.device.mgt.common.device.details.DeviceLocationHistorySnapshotWrapper; +import org.wso2.carbon.device.mgt.common.type.mgt.DeviceStatus; import java.io.Serializable; +import java.util.ArrayList; import java.util.List; @ApiModel(value = "Device", description = "This class carries all information related to a managed device.") @@ -72,6 +74,17 @@ public class Device implements Serializable { required = false) private List applications; + @ApiModelProperty(name = "cost", value = "Cost charged per device.", required = false) + private double cost; + + @ApiModelProperty(name = "daysUsed", value = "Number of days gone since device enrollment.", + required = false) + private int daysUsed; + + @ApiModelProperty(name = "deviceStatusInfo", value = "This defines the device status details. " + + "It is mandatory to define this information.", required = false) + private List deviceStatusInfo = new ArrayList<>(); + @ApiModelProperty( name = "historySnapshot", value = "device history snapshots") @@ -92,6 +105,30 @@ public class Device implements Serializable { this.properties = properties; } + public double getCost() { + return cost; + } + + public void setCost(double cost) { + this.cost = cost; + } + + public int getDaysUsed() { + return daysUsed; + } + + public void setDaysUsed(int daysUsed) { + this.daysUsed = daysUsed; + } + + public List getDeviceStatusInfo() { + return deviceStatusInfo; + } + + public void setDeviceStatusInfo(List deviceStatusInfo) { + this.deviceStatusInfo = deviceStatusInfo; + } + public int getId() { return id; } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/DeviceBilling.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/DeviceBilling.java new file mode 100644 index 00000000000..18ac7743c32 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/DeviceBilling.java @@ -0,0 +1,170 @@ +/* + * Copyright (c) 2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. + * + * WSO2 Inc. 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.wso2.carbon.device.mgt.common; + +import com.google.gson.Gson; +import io.swagger.annotations.ApiModel; +import io.swagger.annotations.ApiModelProperty; +import org.wso2.carbon.device.mgt.common.device.details.DeviceInfo; +import org.wso2.carbon.device.mgt.common.type.mgt.DeviceStatus; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +@ApiModel(value = "DeviceBilling", description = "This class carries all information related to a device billing.") +public class DeviceBilling implements Serializable { + + private static final long serialVersionUID = 1998101711L; + + @ApiModelProperty(name = "id", value = "ID of the device in the device information database.", + required = false) + private int id; + + @ApiModelProperty(name = "name", value = "The device name that can be set on the device by the device user.", + required = true) + private String name; + + @ApiModelProperty(name = "description", value = "Additional information on the device.", required = false) + private String description; + + @ApiModelProperty(name = "cost", value = "Cost charged per device.", required = false) + private Double cost; + + @ApiModelProperty(name = "deviceIdentifier", value = "This is a 64-bit number (as a hex string) that is randomly" + + " generated when the user first sets up the device and should" + + " remain constant for the lifetime of the user's device." + + " The value may change if a factory reset is performed on " + + "the device.", + required = false) + private String deviceIdentifier; + + @ApiModelProperty(name = "daysSinceEnrolled", value = "Number of days gone since device enrollment.", + required = false) + private int daysSinceEnrolled; + + @ApiModelProperty(name = "daysUsed", value = "Number of days gone since device enrollment date to date device was removed.", + required = false) + private int daysUsed; + + @ApiModelProperty(name = "enrolmentInfo", value = "This defines the device registration related information. " + + "It is mandatory to define this information.", required = false) + private EnrolmentInfo enrolmentInfo; + + @ApiModelProperty(name = "deviceStatusInfo", value = "This defines the device status details. " + + "It is mandatory to define this information.", required = false) + private List deviceStatusInfo = new ArrayList<>(); + + @ApiModelProperty(name = "advanceInfo", value = "This defines the device registration related information. " + + "It is mandatory to define this information.", required = false) + private DeviceInfo deviceInfo; + + public DeviceBilling() { + } + + public List getDeviceStatusInfo() { + return deviceStatusInfo; + } + + public void setDeviceStatusInfo(List deviceStatusInfo) { + this.deviceStatusInfo = deviceStatusInfo; + } + + public int getDaysUsed() { + return daysUsed; + } + + public void setDaysUsed(int daysUsed) { + this.daysUsed = daysUsed; + } + + public int getDaysSinceEnrolled() { + return daysSinceEnrolled; + } + + public void setDaysSinceEnrolled(int daysSinceEnrolled) { + this.daysSinceEnrolled = daysSinceEnrolled; + } + + public Double getCost() { + return cost; + } + + public void setCost(Double cost) { + this.cost = cost; + } + + public int getId() { + return id; + } + + public void setId(int id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getDeviceIdentifier() { + return deviceIdentifier; + } + + public void setDeviceIdentifier(String deviceIdentifier) { + this.deviceIdentifier = deviceIdentifier; + } + + public EnrolmentInfo getEnrolmentInfo() { + return enrolmentInfo; + } + + public void setEnrolmentInfo(EnrolmentInfo enrolmentInfo) { + this.enrolmentInfo = enrolmentInfo; + } + + public DeviceInfo getDeviceInfo() { + return deviceInfo; + } + + public void setDeviceInfo(DeviceInfo deviceInfo) { + this.deviceInfo = deviceInfo; + } + + @Override + public String toString() { + return new Gson().toJson(this); + } + + @Override + public int hashCode() { + return getDeviceIdentifier().hashCode(); + } + +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/EnrolmentInfo.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/EnrolmentInfo.java index 2e7376ec81e..52d4efe0394 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/EnrolmentInfo.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/EnrolmentInfo.java @@ -22,6 +22,7 @@ import io.swagger.annotations.ApiModel; import io.swagger.annotations.ApiModelProperty; import java.io.Serializable; +import java.math.BigInteger; @ApiModel(value = "EnrolmentInfo", description = "This class carries all information related to a devices enrollment" + " status.") @@ -48,6 +49,8 @@ public class EnrolmentInfo implements Serializable { private Long dateOfEnrolment; @ApiModelProperty(name = "dateOfLastUpdate", value = "Date of the device's last update. This value is not necessary.", required = false ) private Long dateOfLastUpdate; + @ApiModelProperty(name = "lastBilledDate", value = "Date of the device's last billed date", required = false ) + private Long lastBilledDate; @ApiModelProperty(name = "ownership", value = "Defines the ownership details. The ownership type can be any of the" + " following values.\n" + "BYOD - Bring your own device (BYOD).\n" + @@ -92,6 +95,14 @@ public class EnrolmentInfo implements Serializable { this.dateOfEnrolment = dateOfEnrolment; } + public Long getLastBilledDate() { + return lastBilledDate; + } + + public void setLastBilledDate(Long lastBilledDate) { + this.lastBilledDate = lastBilledDate; + } + public Long getDateOfLastUpdate() { return dateOfLastUpdate; } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/PaginationResult.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/PaginationResult.java index 148cc1781a8..553618d80c5 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/PaginationResult.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/PaginationResult.java @@ -44,6 +44,39 @@ public class PaginationResult implements Serializable { @ApiModelProperty(name = "data", value = "This holds the database records that matches given criteria", required = true) private List data; + @ApiModelProperty(name = "totalCost", value = "Total cost of all devices per tenant", required = false) + private double totalCost; + + @ApiModelProperty(name = "billedDateIsValid", value = "Check if user entered date is valid", required = false) + private boolean billedDateIsValid; + + @ApiModelProperty(name = "message", value = "Send information text to the billing UI", required = false) + private String message; + + public boolean isBilledDateIsValid() { + return billedDateIsValid; + } + + public void setBilledDateIsValid(boolean billedDateIsValid) { + this.billedDateIsValid = billedDateIsValid; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public double getTotalCost() { + return totalCost; + } + + public void setTotalCost(double totalCost) { + this.totalCost = totalCost; + } + public int getRecordsTotal() { return recordsTotal; } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/cost/mgt/Cost.java b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/cost/mgt/Cost.java new file mode 100644 index 00000000000..bb91b2eb036 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.common/src/main/java/org/wso2/carbon/device/mgt/common/cost/mgt/Cost.java @@ -0,0 +1,54 @@ +/* + * Copyright (c) 2020, Entgra (Pvt) Ltd. (http://www.entgra.io) All Rights Reserved. + * + * Entgra (Pvt) Ltd. 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.wso2.carbon.device.mgt.common.cost.mgt; + +import com.google.gson.Gson; + +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlRootElement; + +@XmlRootElement(name = "Cost") +public class Cost { + + private String tenantDomain; + private Double cost; + + @XmlElement(name = "tenantDomain", required = true) + public String getTenantDomain() { + return tenantDomain; + } + + public void setTenantDomain(String tenantDomain) { + this.tenantDomain = tenantDomain; + } + + @XmlElement(name = "cost", required = true) + public Double getCost() { + return cost; + } + + public void setCost(Double cost) { + this.cost = cost; + } + + @Override + public String toString() { + return new Gson().toJson(this); + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/DeviceManagementConstants.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/DeviceManagementConstants.java index e9cfa13398a..8e03917f55f 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/DeviceManagementConstants.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/DeviceManagementConstants.java @@ -44,6 +44,8 @@ public final class DeviceManagementConstants { public static final String DEVICE_CACHE = "DEVICE_CACHE"; public static final String API_RESOURCE_PERMISSION_CACHE = "API_RESOURCE_CACHE_CACHE"; public static final String GEOFENCE_CACHE = "GEOFENCE_CACHE"; + public static final String META_KEY = "PER_DEVICE_COST"; + public static final String ACTIVE_STATUS = "ACTIVE"; public static final String ENROLLMENT_NOTIFICATION_API_ENDPOINT = "/api/device-mgt/enrollment-notification"; public static final String URL_SEPERATOR = "/"; diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/ui/Billing.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/ui/Billing.java new file mode 100644 index 00000000000..11953bd3d22 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/ui/Billing.java @@ -0,0 +1,66 @@ +package org.wso2.carbon.device.mgt.core.config.ui; + +import javax.xml.bind.annotation.XmlElement; + +public class Billing { + private boolean isHideBillGenerationInSuperTenant; + private boolean isHideBillGenerationInSubTenant; + private boolean isHideTotalCalculationInSuperTenant; + private boolean isHideTotalCalculationInSubTenant; + private boolean isHideDomainSelectionInSuperTenant; + private boolean isHideDomainSelectionInSubTenant; + + @XmlElement(name = "HideDomainSelectionInSuperTenant") + public boolean isHideDomainSelectionInSuperTenant() { + return isHideDomainSelectionInSuperTenant; + } + + public void setHideDomainSelectionInSuperTenant(boolean hideDomainSelectionInSuperTenant) { + isHideDomainSelectionInSuperTenant = hideDomainSelectionInSuperTenant; + } + + @XmlElement(name = "HideDomainSelectionInSubTenant") + public boolean isHideDomainSelectionInSubTenant() { + return isHideDomainSelectionInSubTenant; + } + + public void setHideDomainSelectionInSubTenant(boolean hideDomainSelectionInSubTenant) { + isHideDomainSelectionInSubTenant = hideDomainSelectionInSubTenant; + } + + @XmlElement(name = "HideBillGenerationInSuperTenant") + public boolean isHideBillGenerationInSuperTenant() { + return isHideBillGenerationInSuperTenant; + } + + public void setHideBillGenerationInSuperTenant(boolean hideBillGenerationInSuperTenant) { + isHideBillGenerationInSuperTenant = hideBillGenerationInSuperTenant; + } + + @XmlElement(name = "HideBillGenerationInSubTenant") + public boolean isHideBillGenerationInSubTenant() { + return isHideBillGenerationInSubTenant; + } + + public void setHideBillGenerationInSubTenant(boolean hideBillGenerationInSubTenant) { + isHideBillGenerationInSubTenant = hideBillGenerationInSubTenant; + } + + @XmlElement(name = "HideTotalCalculationInSuperTenant") + public boolean isHideTotalCalculationInSuperTenant() { + return isHideTotalCalculationInSuperTenant; + } + + public void setHideTotalCalculationInSuperTenant(boolean hideTotalCalculationInSuperTenant) { + isHideTotalCalculationInSuperTenant = hideTotalCalculationInSuperTenant; + } + + @XmlElement(name = "HideTotalCalculationInSubTenant") + public boolean isHideTotalCalculationInSubTenant() { + return isHideTotalCalculationInSubTenant; + } + + public void setHideTotalCalculationInSubTenant(boolean hideTotalCalculationInSubTenant) { + isHideTotalCalculationInSubTenant = hideTotalCalculationInSubTenant; + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/ui/UIConfiguration.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/ui/UIConfiguration.java index f494007330e..551c1558ea3 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/ui/UIConfiguration.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/config/ui/UIConfiguration.java @@ -33,6 +33,7 @@ public class UIConfiguration { private boolean isSsoEnable; private int sessionTimeOut; private int loginCacheCapacity; + private Billing billing; @XmlElement(name = "AppRegistration", required=true) public AppRegistration getAppRegistration() { @@ -62,6 +63,15 @@ public class UIConfiguration { isSsoEnable = ssoEnable; } + @XmlElement(name = "Billing", required=true) + public Billing getBilling() { + return billing; + } + + public void setBilling(Billing billing) { + this.billing = billing; + } + @XmlElement(name = "SessionTimeOut") public int getSessionTimeOut() { return sessionTimeOut; diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/BillingDAO.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/BillingDAO.java new file mode 100644 index 00000000000..dd0ddf4e286 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/BillingDAO.java @@ -0,0 +1,13 @@ +package org.wso2.carbon.device.mgt.core.dao; + +import org.wso2.carbon.device.mgt.common.Billing; + +import java.sql.Timestamp; +import java.util.List; + +public interface BillingDAO { + + void addBilling(int deviceId, int tenantId, Timestamp billingStart, Timestamp billingEnd) throws DeviceManagementDAOException; + + List getBilling(int deviceId, Timestamp billingStart, Timestamp billingEnd) throws DeviceManagementDAOException; +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceDAO.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceDAO.java index 40eefe935e1..8f23228bef9 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceDAO.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceDAO.java @@ -36,12 +36,8 @@ package org.wso2.carbon.device.mgt.core.dao; import org.apache.commons.collections.map.SingletonMap; -import org.wso2.carbon.device.mgt.common.Device; -import org.wso2.carbon.device.mgt.common.DeviceIdentifier; -import org.wso2.carbon.device.mgt.common.EnrolmentInfo; +import org.wso2.carbon.device.mgt.common.*; import org.wso2.carbon.device.mgt.common.EnrolmentInfo.Status; -import org.wso2.carbon.device.mgt.common.PaginationRequest; -import org.wso2.carbon.device.mgt.common.Count; import org.wso2.carbon.device.mgt.common.configuration.mgt.DevicePropertyInfo; import org.wso2.carbon.device.mgt.common.device.details.DeviceData; import org.wso2.carbon.device.mgt.common.device.details.DeviceLocationHistorySnapshot; @@ -49,9 +45,9 @@ import org.wso2.carbon.device.mgt.common.device.details.DeviceMonitoringData; import org.wso2.carbon.device.mgt.common.geo.service.GeoQuery; import org.wso2.carbon.device.mgt.core.dto.DeviceType; import org.wso2.carbon.device.mgt.common.geo.service.GeoCluster; -import org.wso2.carbon.device.mgt.common.geo.service.GeoCoordinate; import java.sql.SQLException; +import java.sql.Timestamp; import java.util.Date; import java.util.List; import java.util.Map; @@ -297,6 +293,14 @@ public interface DeviceDAO { */ List getDevices(PaginationRequest request, int tenantId) throws DeviceManagementDAOException; + /** + * This method is used to retrieve the devices of a given tenant without pagination. + * @param tenantId tenant id. + * @return returns a list of devices of the tenant. + * @throws DeviceManagementDAOException + */ + List getDeviceListWithoutPagination(int tenantId) throws DeviceManagementDAOException; + /** * This method is used to retrieve the devices of a given tenant as a paginated result, along the lines of * activeServerCount and serverIndex diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceManagementDAOFactory.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceManagementDAOFactory.java index a07989e3385..6b594664f4f 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceManagementDAOFactory.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceManagementDAOFactory.java @@ -42,6 +42,7 @@ import org.wso2.carbon.device.mgt.core.privacy.dao.impl.PrivacyComplianceDAOImpl import javax.sql.DataSource; import java.sql.Connection; import java.sql.SQLException; +import java.sql.Timestamp; import java.util.Hashtable; import java.util.List; @@ -124,6 +125,11 @@ public class DeviceManagementDAOFactory { public static EnrollmentDAO getEnrollmentDAO() { return new EnrollmentDAOImpl(); } + + public static BillingDAO getBillingDAO() { + return new BillingDAOImpl(); + } + public static DeviceStatusDAO getDeviceStatusDAO() { return new DeviceStatusDAOImpl(); } diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceStatusDAO.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceStatusDAO.java index 6d9cb18e585..56ccc9d95f9 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceStatusDAO.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/DeviceStatusDAO.java @@ -34,7 +34,7 @@ public interface DeviceStatusDAO { List getStatus(int deviceId, int tenantId) throws DeviceManagementDAOException; - List getStatus(int deviceId, int tenantId, Date fromDate, Date toDate) throws DeviceManagementDAOException; + List getStatus(int deviceId, int tenantId, Date fromDate, Date toDate, boolean billingStatus) throws DeviceManagementDAOException; List getStatus(int enrolmentId) throws DeviceManagementDAOException; diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/EnrollmentDAO.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/EnrollmentDAO.java index be621eab347..825fa647979 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/EnrollmentDAO.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/EnrollmentDAO.java @@ -22,6 +22,7 @@ import org.wso2.carbon.device.mgt.common.Device; import org.wso2.carbon.device.mgt.common.EnrolmentInfo; import org.wso2.carbon.device.mgt.common.EnrolmentInfo.Status; +import java.sql.Timestamp; import java.util.List; public interface EnrollmentDAO { @@ -32,6 +33,8 @@ public interface EnrollmentDAO { boolean updateEnrollmentStatus(List enrolmentInfos) throws DeviceManagementDAOException; + boolean updateEnrollmentLastBilledDate(EnrolmentInfo enrolmentInfos, Timestamp lastBilledDate, int tenantId) throws DeviceManagementDAOException; + int removeEnrollment(int deviceId, String currentOwner, int tenantId) throws DeviceManagementDAOException; @Deprecated diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/BillingDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/BillingDAOImpl.java new file mode 100644 index 00000000000..4af343012b0 --- /dev/null +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/BillingDAOImpl.java @@ -0,0 +1,71 @@ +package org.wso2.carbon.device.mgt.core.dao.impl; + +import org.wso2.carbon.device.mgt.common.Billing; +import org.wso2.carbon.device.mgt.common.EnrolmentInfo; +import org.wso2.carbon.device.mgt.core.dao.BillingDAO; +import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOException; +import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOFactory; +import org.wso2.carbon.device.mgt.core.dao.util.DeviceManagementDAOUtil; + +import java.sql.*; +import java.util.ArrayList; +import java.util.List; + +public class BillingDAOImpl implements BillingDAO { + + @Override + public void addBilling(int deviceId, int tenantId, Timestamp billingStart, Timestamp billingEnd) throws DeviceManagementDAOException { + + Connection conn; + PreparedStatement stmt = null; + ResultSet rs = null; + try { + conn = this.getConnection(); + String sql = "INSERT INTO DM_BILLING(DEVICE_ID, TENANT_ID, BILLING_START, BILLING_END) VALUES(?, ?, ?, ?)"; + stmt = conn.prepareStatement(sql, new String[] {"invoice_id"}); + stmt.setInt(1, deviceId); + stmt.setInt(2,tenantId); + stmt.setTimestamp(3, billingStart); + stmt.setTimestamp(4, billingEnd); + stmt.execute(); + } catch (SQLException e) { + e.printStackTrace(); + throw new DeviceManagementDAOException("Error occurred while adding billing period", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, rs); + } + } + + @Override + public List getBilling(int deviceId, Timestamp billingStart, Timestamp billingEnd) throws DeviceManagementDAOException { + List billings = new ArrayList<>(); + Connection conn; + PreparedStatement stmt = null; + ResultSet rs = null; + EnrolmentInfo.Status status = null; + try { + conn = this.getConnection(); + String sql; + + sql = "SELECT * FROM DM_BILLING WHERE DEVICE_ID = ?"; + stmt = conn.prepareStatement(sql); + stmt.setInt(1, deviceId); + rs = stmt.executeQuery(); + + while (rs.next()) { + Billing bill = new Billing(rs.getInt("INVOICE_ID"), rs.getInt("DEVICE_ID"),rs.getInt("TENANT_ID"), + (rs.getTimestamp("BILLING_START").getTime()), (rs.getTimestamp("BILLING_END").getTime())); + billings.add(bill); + } + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred getting billing periods", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, null); + } + return billings; + } + + private Connection getConnection() throws SQLException { + return DeviceManagementDAOFactory.getConnection(); + } +} diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/DeviceStatusDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/DeviceStatusDAOImpl.java index 0305f831145..c237d4ce22d 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/DeviceStatusDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/DeviceStatusDAOImpl.java @@ -15,7 +15,7 @@ import java.util.List; public class DeviceStatusDAOImpl implements DeviceStatusDAO { - private List getStatus(int id, Date fromDate, Date toDate, boolean isDeviceId) throws DeviceManagementDAOException { + private List getStatus(int id, Date fromDate, Date toDate, boolean isDeviceId, boolean billingStatus) throws DeviceManagementDAOException { List result = new ArrayList<>(); Connection conn; PreparedStatement stmt = null; @@ -25,7 +25,14 @@ public class DeviceStatusDAOImpl implements DeviceStatusDAO { conn = this.getConnection(); // either we list all status values for the device using the device id or only get status values for the given enrolment id String idType = isDeviceId ? "DEVICE_ID" : "ENROLMENT_ID"; - String sql = "SELECT ENROLMENT_ID, DEVICE_ID, UPDATE_TIME, STATUS, CHANGED_BY FROM DM_DEVICE_STATUS WHERE " + idType + " = ?"; + String sql; + + if (billingStatus) { + sql = "SELECT ENROLMENT_ID, DEVICE_ID, UPDATE_TIME, STATUS, CHANGED_BY FROM DM_DEVICE_STATUS WHERE STATUS IN ('ACTIVE','REMOVED') AND " + idType + " = ?"; + } else { + sql = "SELECT ENROLMENT_ID, DEVICE_ID, UPDATE_TIME, STATUS, CHANGED_BY FROM DM_DEVICE_STATUS WHERE " + idType + " = ?"; + } + // filter the data based on a date range if specified if (fromDate != null){ sql += " AND UPDATE_TIME >= ?"; @@ -64,17 +71,17 @@ public class DeviceStatusDAOImpl implements DeviceStatusDAO { @Override public List getStatus(int enrolmentId, Date fromDate, Date toDate) throws DeviceManagementDAOException { - return getStatus(enrolmentId, fromDate, toDate, false); + return getStatus(enrolmentId, fromDate, toDate, false, false); } @Override public List getStatus(int deviceId, int tenantId) throws DeviceManagementDAOException { - return getStatus(deviceId, tenantId, null, null); + return getStatus(deviceId, tenantId, null, null, false); } @Override - public List getStatus(int deviceId, int tenantId, Date fromDate, Date toDate) throws DeviceManagementDAOException { - return getStatus(deviceId, fromDate, toDate, true); + public List getStatus(int deviceId, int tenantId, Date fromDate, Date toDate, boolean billingStatus) throws DeviceManagementDAOException { + return getStatus(deviceId, fromDate, toDate, true, billingStatus); } @Override diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/EnrollmentDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/EnrollmentDAOImpl.java index 1472518b1cb..a8fbad8ff96 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/EnrollmentDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/EnrollmentDAOImpl.java @@ -144,6 +144,27 @@ public class EnrollmentDAOImpl implements EnrollmentDAO { return status; } + @Override + public boolean updateEnrollmentLastBilledDate(EnrolmentInfo enrolmentInfo, Timestamp lastBilledDate, int tenantId) throws DeviceManagementDAOException { + Connection conn; + PreparedStatement stmt = null; + ResultSet rs = null; + try { + conn = this.getConnection(); + String sql = "UPDATE DM_ENROLMENT SET LAST_BILLED_DATE = ? WHERE ID = ? AND TENANT_ID = ?"; + stmt = conn.prepareStatement(sql); + stmt.setLong(1, lastBilledDate.getTime()); + stmt.setInt(2, enrolmentInfo.getId()); + stmt.setInt(3, tenantId); + stmt.executeUpdate(); + return true; + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while updating enrolment last billed date.", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, rs); + } + } + @Override public int removeEnrollment(int deviceId, String currentOwner, diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/GenericDeviceDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/GenericDeviceDAOImpl.java index aff4465a04d..9e9da571496 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/GenericDeviceDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/GenericDeviceDAOImpl.java @@ -18,7 +18,6 @@ package org.wso2.carbon.device.mgt.core.dao.impl.device; -import org.apache.commons.lang.StringUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.device.mgt.common.Count; @@ -85,6 +84,7 @@ public class GenericDeviceDAOImpl extends AbstractDeviceDAOImpl { "e.IS_TRANSFERRED, " + "e.DATE_OF_LAST_UPDATE, " + "e.DATE_OF_ENROLMENT, " + + "e.LAST_BILLED_DATE, " + "e.ID AS ENROLMENT_ID " + "FROM DM_ENROLMENT e, " + "(SELECT d.ID, " + @@ -188,6 +188,34 @@ public class GenericDeviceDAOImpl extends AbstractDeviceDAOImpl { } } + @Override + public List getDeviceListWithoutPagination(int tenantId) + throws DeviceManagementDAOException { + Connection conn; + PreparedStatement stmt = null; + List devices = new ArrayList<>(); + try { + conn = this.getConnection(); + String sql = "SELECT DM_DEVICE.ID AS DEVICE_ID, DEVICE_IDENTIFICATION, DESCRIPTION, DM_DEVICE.NAME AS DEVICE_NAME, DM_DEVICE_TYPE.NAME AS DEVICE_TYPE,\n" + + "DM_ENROLMENT.ID AS ENROLMENT_ID, DATE_OF_ENROLMENT,OWNER, OWNERSHIP,IS_TRANSFERRED, STATUS, DATE_OF_LAST_UPDATE, LAST_BILLED_DATE,\n" + + "TIMESTAMPDIFF('DAY', DATE_OF_ENROLMENT, CURDATE()) as DAYS_SINCE_ENROLLED FROM DM_DEVICE JOIN DM_ENROLMENT\n" + + "ON (DM_DEVICE.ID = DM_ENROLMENT.DEVICE_ID) JOIN DM_DEVICE_TYPE ON (DM_DEVICE.DEVICE_TYPE_ID = DM_DEVICE_TYPE.ID) WHERE DM_ENROLMENT.TENANT_ID=?"; + stmt = conn.prepareStatement(sql); + stmt.setInt(1, tenantId); + ResultSet rs = stmt.executeQuery(); + + while (rs.next()) { + Device device = DeviceManagementDAOUtil.loadDevice(rs); + devices.add(device); + } + } catch (SQLException e) { + throw new DeviceManagementDAOException("Error occurred while fetching the list of device billing ", e); + } finally { + DeviceManagementDAOUtil.cleanupResources(stmt, null); + } + return devices; + } + @Override public List getAllocatedDevices(PaginationRequest request, int tenantId, int activeServerCount, int serverIndex) throws DeviceManagementDAOException { diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/OracleDeviceDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/OracleDeviceDAOImpl.java index f2a91cae452..beef6f15421 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/OracleDeviceDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/OracleDeviceDAOImpl.java @@ -23,6 +23,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.device.mgt.common.Count; import org.wso2.carbon.device.mgt.common.Device; +import org.wso2.carbon.device.mgt.common.DeviceBilling; import org.wso2.carbon.device.mgt.common.PaginationRequest; import org.wso2.carbon.device.mgt.common.device.details.DeviceInfo; import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOException; @@ -187,6 +188,11 @@ public class OracleDeviceDAOImpl extends AbstractDeviceDAOImpl { } } + @Override + public List getDeviceListWithoutPagination(int tenantId) throws DeviceManagementDAOException { + return null; + } + @Override public List getAllocatedDevices(PaginationRequest request, int tenantId, int activeServerCount, int serverIndex) diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/PostgreSQLDeviceDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/PostgreSQLDeviceDAOImpl.java index 66313603cb6..eb358004abf 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/PostgreSQLDeviceDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/PostgreSQLDeviceDAOImpl.java @@ -23,6 +23,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.device.mgt.common.Count; import org.wso2.carbon.device.mgt.common.Device; +import org.wso2.carbon.device.mgt.common.DeviceBilling; import org.wso2.carbon.device.mgt.common.PaginationRequest; import org.wso2.carbon.device.mgt.common.device.details.DeviceInfo; import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOException; @@ -178,6 +179,11 @@ public class PostgreSQLDeviceDAOImpl extends AbstractDeviceDAOImpl { } } + @Override + public List getDeviceListWithoutPagination(int tenantId) throws DeviceManagementDAOException { + return null; + } + @Override public List getAllocatedDevices(PaginationRequest request, int tenantId, int activeServerCount, int serverIndex) diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/SQLServerDeviceDAOImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/SQLServerDeviceDAOImpl.java index ae4b25b4315..f9e087e64e2 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/SQLServerDeviceDAOImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/impl/device/SQLServerDeviceDAOImpl.java @@ -23,6 +23,7 @@ import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.device.mgt.common.Count; import org.wso2.carbon.device.mgt.common.Device; +import org.wso2.carbon.device.mgt.common.DeviceBilling; import org.wso2.carbon.device.mgt.common.PaginationRequest; import org.wso2.carbon.device.mgt.common.device.details.DeviceInfo; import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOException; @@ -188,6 +189,11 @@ public class SQLServerDeviceDAOImpl extends AbstractDeviceDAOImpl { } } + @Override + public List getDeviceListWithoutPagination(int tenantId) throws DeviceManagementDAOException { + return null; + } + @Override public List getAllocatedDevices(PaginationRequest request, int tenantId, int activeServerCount, int serverIndex) diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/util/DeviceManagementDAOUtil.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/util/DeviceManagementDAOUtil.java index 8beb17b5a0e..1f031e7c4e0 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/util/DeviceManagementDAOUtil.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/dao/util/DeviceManagementDAOUtil.java @@ -21,16 +21,20 @@ import java.sql.*; import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneId; +import java.util.*; import java.util.Date; + import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.context.CarbonContext; import org.wso2.carbon.device.mgt.common.Device; +import org.wso2.carbon.device.mgt.common.DeviceBilling; import org.wso2.carbon.device.mgt.common.DeviceIdentifier; import org.wso2.carbon.device.mgt.common.EnrolmentInfo; import org.wso2.carbon.device.mgt.common.device.details.DeviceInfo; import org.wso2.carbon.device.mgt.common.device.details.DeviceLocationHistorySnapshot; import org.wso2.carbon.device.mgt.common.device.details.DeviceMonitoringData; +import org.wso2.carbon.device.mgt.common.type.mgt.DeviceStatus; import org.wso2.carbon.device.mgt.core.dao.DeviceManagementDAOException; import org.wso2.carbon.device.mgt.core.dto.DeviceType; import org.wso2.carbon.device.mgt.core.internal.DeviceManagementDataHolder; @@ -40,9 +44,6 @@ import org.wso2.carbon.utils.multitenancy.MultitenantConstants; import javax.naming.InitialContext; import javax.sql.DataSource; -import java.util.HashMap; -import java.util.Hashtable; -import java.util.Map; public final class DeviceManagementDAOUtil { @@ -142,6 +143,14 @@ public final class DeviceManagementDAOUtil { public static EnrolmentInfo loadEnrolment(ResultSet rs) throws SQLException { EnrolmentInfo enrolmentInfo = new EnrolmentInfo(); + String columnName = "LAST_BILLED_DATE"; + ResultSetMetaData rsmd = rs.getMetaData(); + int columns = rsmd.getColumnCount(); + for (int x = 1; x <= columns; x++) { + if (columnName.equals(rsmd.getColumnName(x))) { + enrolmentInfo.setLastBilledDate(rs.getLong("LAST_BILLED_DATE")); + } + } enrolmentInfo.setId(rs.getInt("ENROLMENT_ID")); enrolmentInfo.setOwner(rs.getString("OWNER")); enrolmentInfo.setOwnership(EnrolmentInfo.OwnerShip.valueOf(rs.getString("OWNERSHIP"))); @@ -152,6 +161,18 @@ public final class DeviceManagementDAOUtil { return enrolmentInfo; } + public static EnrolmentInfo loadEnrolmentBilling(ResultSet rs) throws SQLException { + EnrolmentInfo enrolmentInfo = new EnrolmentInfo(); + enrolmentInfo.setId(rs.getInt("ENROLMENT_ID")); + enrolmentInfo.setDateOfEnrolment(rs.getTimestamp("DATE_OF_ENROLMENT").getTime()); + enrolmentInfo.setLastBilledDate(rs.getLong("LAST_BILLED_DATE")); + enrolmentInfo.setStatus(EnrolmentInfo.Status.valueOf(rs.getString("STATUS"))); + if (EnrolmentInfo.Status.valueOf(rs.getString("STATUS")).equals("REMOVED")) { + enrolmentInfo.setDateOfLastUpdate(rs.getTimestamp("DATE_OF_LAST_UPDATE").getTime()); + } + return enrolmentInfo; + } + public static EnrolmentInfo loadMatchingEnrolment(ResultSet rs) throws SQLException { Map enrolmentInfos = new HashMap<>(); EnrolmentInfo enrolmentInfo = loadEnrolment(rs); @@ -195,6 +216,23 @@ public final class DeviceManagementDAOUtil { device.setDeviceIdentifier(rs.getString("DEVICE_IDENTIFICATION")); device.setEnrolmentInfo(loadEnrolment(rs)); return device; + } + + public static DeviceBilling loadDeviceBilling(ResultSet rs) throws SQLException { + DeviceBilling device = new DeviceBilling(); + device.setId(rs.getInt("ID")); + device.setName(rs.getString("DEVICE_NAME")); + device.setDescription(rs.getString("DESCRIPTION")); + device.setDeviceIdentifier(rs.getString("DEVICE_IDENTIFICATION")); + device.setDaysUsed((int) rs.getLong("DAYS_SINCE_ENROLLED")); + device.setEnrolmentInfo(loadEnrolmentBilling(rs)); + return device; +// if (removedDevices) { +// device.setDaysUsed((int) rs.getLong("DAYS_USED")); +// } else { +// device.setDaysSinceEnrolled((int) rs.getLong("DAYS_SINCE_ENROLLED")); +// } + } public static DeviceMonitoringData loadDevice(ResultSet rs, String deviceTypeName) throws SQLException { diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderService.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderService.java index a8f249359bc..4b1a424d27a 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderService.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderService.java @@ -36,18 +36,7 @@ package org.wso2.carbon.device.mgt.core.service; import org.apache.commons.collections.map.SingletonMap; -import org.wso2.carbon.device.mgt.common.ActivityPaginationRequest; -import org.wso2.carbon.device.mgt.common.Device; -import org.wso2.carbon.device.mgt.common.DeviceIdentifier; -import org.wso2.carbon.device.mgt.common.DeviceTransferRequest; -import org.wso2.carbon.device.mgt.common.DynamicTaskContext; -import org.wso2.carbon.device.mgt.common.EnrolmentInfo; -import org.wso2.carbon.device.mgt.common.FeatureManager; -import org.wso2.carbon.device.mgt.common.MonitoringOperation; -import org.wso2.carbon.device.mgt.common.OperationMonitoringTaskConfig; -import org.wso2.carbon.device.mgt.common.PaginationRequest; -import org.wso2.carbon.device.mgt.common.PaginationResult; -import org.wso2.carbon.device.mgt.common.StartupOperationConfig; +import org.wso2.carbon.device.mgt.common.*; import org.wso2.carbon.device.mgt.common.app.mgt.ApplicationManagementException; import org.wso2.carbon.device.mgt.common.configuration.mgt.AmbiguousConfigurationException; import org.wso2.carbon.device.mgt.common.configuration.mgt.ConfigurationManagementException; @@ -80,6 +69,8 @@ import org.wso2.carbon.device.mgt.common.geo.service.GeoCluster; import org.wso2.carbon.device.mgt.common.geo.service.GeoCoordinate; import java.sql.SQLException; +import java.sql.Timestamp; +import java.util.Collection; import java.util.Date; import java.util.List; import java.util.Map; @@ -208,6 +199,27 @@ public interface DeviceManagementProviderService { */ PaginationResult getAllDevices(PaginationRequest request, boolean requireDeviceInfo) throws DeviceManagementException; + /** + * Method to retrieve all the devices with pagination support. + * + * @param request PaginationRequest object holding the data for pagination + * @return PaginationResult - Result including the required parameters necessary to do pagination. + * @throws DeviceManagementException If some unusual behaviour is observed while fetching billing of + * devices. + */ + PaginationResult getAllDevicesBillings(PaginationRequest request, int tenantId, String tenantDomain, Timestamp startDate, Timestamp endDate, boolean generateBill) throws DeviceManagementException; + + /** + * Method to retrieve all the devices with pagination support. + * + * @return PaginationResult - Result including the device bill list without pagination. + * @throws DeviceManagementException If some unusual behaviour is observed while fetching billing of + * devices. + */ + PaginationResult createBillingFile(int tenantId, String tenantDomain, Timestamp startDate, Timestamp endDate, boolean generateBill) throws DeviceManagementException; + + + /** * Returns the device of specified id. * @@ -693,7 +705,7 @@ public interface DeviceManagementProviderService { List getDeviceStatusHistory(Device device) throws DeviceManagementException; - List getDeviceStatusHistory(Device device, Date fromDate, Date toDate) throws DeviceManagementException; + List getDeviceStatusHistory(Device device, Date fromDate, Date toDate, boolean billingStatus) throws DeviceManagementException; List getDeviceCurrentEnrolmentStatusHistory(Device device) throws DeviceManagementException; diff --git a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderServiceImpl.java b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderServiceImpl.java index 1e17273481a..d9bb601faeb 100644 --- a/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderServiceImpl.java +++ b/components/device-mgt/org.wso2.carbon.device.mgt.core/src/main/java/org/wso2/carbon/device/mgt/core/service/DeviceManagementProviderServiceImpl.java @@ -34,6 +34,7 @@ */ package org.wso2.carbon.device.mgt.core.service; +import com.google.common.reflect.TypeToken; import com.google.gson.Gson; import org.apache.commons.collections.map.SingletonMap; import org.apache.commons.lang.StringUtils; @@ -49,23 +50,7 @@ import org.apache.http.protocol.HTTP; import org.wso2.carbon.CarbonConstants; import org.wso2.carbon.context.CarbonContext; import org.wso2.carbon.context.PrivilegedCarbonContext; -import org.wso2.carbon.device.mgt.common.ActivityPaginationRequest; -import org.wso2.carbon.device.mgt.common.Device; -import org.wso2.carbon.device.mgt.common.DeviceEnrollmentInfoNotification; -import org.wso2.carbon.device.mgt.common.DeviceIdentifier; -import org.wso2.carbon.device.mgt.common.DeviceManager; -import org.wso2.carbon.device.mgt.common.DeviceNotification; -import org.wso2.carbon.device.mgt.common.DevicePropertyNotification; -import org.wso2.carbon.device.mgt.common.DeviceTransferRequest; -import org.wso2.carbon.device.mgt.common.DynamicTaskContext; -import org.wso2.carbon.device.mgt.common.EnrolmentInfo; -import org.wso2.carbon.device.mgt.common.FeatureManager; -import org.wso2.carbon.device.mgt.common.InitialOperationConfig; -import org.wso2.carbon.device.mgt.common.MonitoringOperation; -import org.wso2.carbon.device.mgt.common.OperationMonitoringTaskConfig; -import org.wso2.carbon.device.mgt.common.PaginationRequest; -import org.wso2.carbon.device.mgt.common.PaginationResult; -import org.wso2.carbon.device.mgt.common.StartupOperationConfig; +import org.wso2.carbon.device.mgt.common.*; import org.wso2.carbon.device.mgt.common.app.mgt.Application; import org.wso2.carbon.device.mgt.common.app.mgt.ApplicationManagementException; import org.wso2.carbon.device.mgt.common.configuration.mgt.AmbiguousConfigurationException; @@ -76,6 +61,7 @@ import org.wso2.carbon.device.mgt.common.configuration.mgt.DeviceConfiguration; import org.wso2.carbon.device.mgt.common.configuration.mgt.DevicePropertyInfo; import org.wso2.carbon.device.mgt.common.configuration.mgt.EnrollmentConfiguration; import org.wso2.carbon.device.mgt.common.configuration.mgt.PlatformConfiguration; +import org.wso2.carbon.device.mgt.common.cost.mgt.Cost; import org.wso2.carbon.device.mgt.common.device.details.DeviceData; import org.wso2.carbon.device.mgt.common.device.details.DeviceInfo; import org.wso2.carbon.device.mgt.common.device.details.DeviceLocation; @@ -99,6 +85,7 @@ import org.wso2.carbon.device.mgt.common.group.mgt.GroupManagementException; import org.wso2.carbon.device.mgt.common.invitation.mgt.DeviceEnrollmentInvitationDetails; import org.wso2.carbon.device.mgt.common.license.mgt.License; import org.wso2.carbon.device.mgt.common.license.mgt.LicenseManagementException; +import org.wso2.carbon.device.mgt.common.metadata.mgt.Metadata; import org.wso2.carbon.device.mgt.common.operation.mgt.Activity; import org.wso2.carbon.device.mgt.common.operation.mgt.Operation; import org.wso2.carbon.device.mgt.common.operation.mgt.OperationManagementException; @@ -129,6 +116,8 @@ import org.wso2.carbon.device.mgt.common.geo.service.GeoCoordinate; import org.wso2.carbon.device.mgt.core.internal.DeviceManagementDataHolder; import org.wso2.carbon.device.mgt.core.internal.DeviceManagementServiceComponent; import org.wso2.carbon.device.mgt.core.internal.PluginInitializationListener; +import org.wso2.carbon.device.mgt.core.metadata.mgt.dao.MetadataDAO; +import org.wso2.carbon.device.mgt.core.metadata.mgt.dao.MetadataManagementDAOFactory; import org.wso2.carbon.device.mgt.core.operation.mgt.CommandOperation; import org.wso2.carbon.device.mgt.core.util.DeviceManagerUtil; import org.wso2.carbon.email.sender.core.ContentProviderInfo; @@ -140,23 +129,20 @@ import org.wso2.carbon.email.sender.core.service.EmailSenderService; import org.wso2.carbon.stratos.common.beans.TenantInfoBean; import org.wso2.carbon.tenant.mgt.services.TenantMgtAdminService; import org.wso2.carbon.user.api.UserStoreException; +import org.wso2.carbon.utils.multitenancy.MultitenantConstants; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; import java.io.IOException; import java.io.StringWriter; +import java.lang.reflect.Type; import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Calendar; -import java.util.Collections; -import java.util.Date; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.HashSet; -import java.util.List; -import java.util.Map; -import java.util.Properties; +import java.sql.Timestamp; +import java.text.Format; +import java.text.SimpleDateFormat; +import java.util.*; +import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; //import org.wso2.carbon.device.mgt.analytics.data.publisher.exception.DataPublisherConfigurationException; @@ -172,6 +158,8 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv private final DeviceTypeDAO deviceTypeDAO; private final EnrollmentDAO enrollmentDAO; private final ApplicationDAO applicationDAO; + private MetadataDAO metadataDAO; + private final BillingDAO billingDAO; private final DeviceStatusDAO deviceStatusDAO; public DeviceManagementProviderServiceImpl() { @@ -180,6 +168,8 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv this.applicationDAO = DeviceManagementDAOFactory.getApplicationDAO(); this.deviceTypeDAO = DeviceManagementDAOFactory.getDeviceTypeDAO(); this.enrollmentDAO = DeviceManagementDAOFactory.getEnrollmentDAO(); + this.metadataDAO = MetadataManagementDAOFactory.getMetadataDAO(); + this.billingDAO = DeviceManagementDAOFactory.getBillingDAO(); this.deviceStatusDAO = DeviceManagementDAOFactory.getDeviceStatusDAO(); /* Registering a listener to retrieve events when some device management service plugin is installed after @@ -783,8 +773,8 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv throw new DeviceManagementException(msg); } if (log.isDebugEnabled()) { - log.debug("Getting allocated Devices for Server with index "+ serverIndex + " and" + - " type '" + deviceType); + log.debug("Getting allocated Devices for Server with index " + serverIndex + " and" + + " type '" + deviceType); } List allocatedDevices; try { @@ -798,7 +788,7 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv } } catch (DeviceManagementDAOException e) { String msg = "Error occurred while retrieving all devices of type '" + - deviceType + "' that are being managed within the scope of current tenant"; + deviceType + "' that are being managed within the scope of current tenant"; log.error(msg, e); throw new DeviceManagementException(msg, e); } catch (SQLException e) { @@ -952,6 +942,240 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv return this.getAllDevices(request, true); } + public PaginationResult calculateCost(int tenantId, String tenantDomain, Timestamp startDate, Timestamp endDate, boolean generateBill, List allDevices) throws DeviceManagementException { + + PaginationResult paginationResult = new PaginationResult(); + double totalCost = 0.0; + boolean allDevicesBilledDateIsValid = true; + ArrayList lastBilledDatesList = new ArrayList<>(); + List invalidDevices = new ArrayList<>(); + List removeBillingPeriodInvalidDevices = new ArrayList<>() ; + List removeStatusUpdateInvalidDevices = new ArrayList<>() ; + + try { + MetadataManagementDAOFactory.beginTransaction(); + Metadata metadata = metadataDAO.getMetadata(MultitenantConstants.SUPER_TENANT_ID, DeviceManagementConstants.META_KEY); + + Gson g = new Gson(); + Collection costData = null; + + + Type collectionType = new TypeToken>() {}.getType(); + if (metadata != null) { + costData = g.fromJson(metadata.getMetaValue(), collectionType); + for (Cost tenantCost : costData) { + if (tenantCost.getTenantDomain().equals(tenantDomain)) { + for (Device device : allDevices) { + device.setDeviceStatusInfo(getDeviceStatusHistory(device, null, null, true)); + long dateDiff = 0; + + List deviceStatus = device.getDeviceStatusInfo(); + boolean firstDateBilled = false; + boolean deviceStatusIsValid = false; + + List deviceBilling = billingDAO.getBilling(device.getId(), startDate, endDate); + boolean billDateIsInvalid = false; + + if (deviceBilling.isEmpty()) { + billDateIsInvalid = false; + } + + if (generateBill) { + for (Billing bill : deviceBilling) { + if ((bill.getBillingStart() <= startDate.getTime() && startDate.getTime() <= bill.getBillingEnd()) || + (bill.getBillingStart() <= endDate.getTime() && endDate.getTime() <= bill.getBillingEnd())) { + billDateIsInvalid = true; + invalidDevices.add(bill); + } + } + } + + if (!billDateIsInvalid) { + for (int i = 0; i < deviceStatus.size(); i++) { + if (DeviceManagementConstants.ACTIVE_STATUS.equals(deviceStatus.get(i).getStatus().toString())) { + if (deviceStatus.size() > i + 1) { + if (!firstDateBilled) { + firstDateBilled = true; + if (device.getEnrolmentInfo().getLastBilledDate() == 0) { + deviceStatusIsValid = true; + dateDiff = dateDiff + (deviceStatus.get(i + 1).getUpdateTime().getTime() - deviceStatus.get(i).getUpdateTime().getTime()); + } else { + if (deviceStatus.get(i + 1).getUpdateTime().getTime() >= device.getEnrolmentInfo().getLastBilledDate()) { + deviceStatusIsValid = true; + dateDiff = dateDiff + (deviceStatus.get(i + 1).getUpdateTime().getTime() - device.getEnrolmentInfo().getLastBilledDate()); + } + } + } else { + if (deviceStatus.get(i).getUpdateTime().getTime() >= device.getEnrolmentInfo().getLastBilledDate()) { + deviceStatusIsValid = true; + dateDiff = dateDiff + (deviceStatus.get(i + 1).getUpdateTime().getTime() - deviceStatus.get(i).getUpdateTime().getTime()); + } + } + } else { + + // If only one status row is retrieved this block is executed + if (!firstDateBilled) { + firstDateBilled = true; + + // Is executed if there is no lastBilled date and if the updates time is before the end date + if (device.getEnrolmentInfo().getLastBilledDate() == 0) { + if (endDate.getTime() >= deviceStatus.get(i).getUpdateTime().getTime()) { + deviceStatusIsValid = true; + dateDiff = dateDiff + (endDate.getTime() - deviceStatus.get(i).getUpdateTime().getTime()); + } + } else { + if (endDate.getTime() >= device.getEnrolmentInfo().getLastBilledDate()) { + deviceStatusIsValid = true; + dateDiff = dateDiff + (endDate.getTime() - device.getEnrolmentInfo().getLastBilledDate()); + } + } + } else { + if (device.getEnrolmentInfo().getLastBilledDate() <= deviceStatus.get(i).getUpdateTime().getTime() + && endDate.getTime() >= deviceStatus.get(i).getUpdateTime().getTime()) { + deviceStatusIsValid = true; + dateDiff = dateDiff + (endDate.getTime() - deviceStatus.get(i).getUpdateTime().getTime()); + } + if (device.getEnrolmentInfo().getLastBilledDate() >= deviceStatus.get(i).getUpdateTime().getTime() + && endDate.getTime() >= device.getEnrolmentInfo().getLastBilledDate()) { + deviceStatusIsValid = true; + dateDiff = dateDiff + (endDate.getTime() - device.getEnrolmentInfo().getLastBilledDate()); + } + } + } + } + } + + long dateInDays = TimeUnit.DAYS.convert(dateDiff, TimeUnit.MILLISECONDS); + double cost = (tenantCost.getCost() / 365) * dateInDays; + totalCost = cost + totalCost; + device.setCost(Math.round(cost * 100.0) / 100.0); + device.setDaysUsed((int) dateInDays); + + if (generateBill) { + enrollmentDAO.updateEnrollmentLastBilledDate(device.getEnrolmentInfo(), endDate, tenantId); + billingDAO.addBilling(device.getId(), tenantId, startDate, endDate); + DeviceManagementDAOFactory.commitTransaction(); + } + + } else { + + for (int i = 0; i < deviceStatus.size(); i++) { + if (endDate.getTime() >= deviceStatus.get(i).getUpdateTime().getTime() + && startDate.getTime() <= deviceStatus.get(i).getUpdateTime().getTime()) { + deviceStatusIsValid = true; + } + } + if (device.getEnrolmentInfo().getLastBilledDate() != 0) { + Date date = new Date(device.getEnrolmentInfo().getLastBilledDate()); + Format format = new SimpleDateFormat("yyyy MM dd"); + + for (String lastBillDate : lastBilledDatesList) { + if (!lastBillDate.equals(format.format(date))) { + lastBilledDatesList.add(format.format(date)); + } + } + } + removeBillingPeriodInvalidDevices.add(device); + } + + if (!deviceStatusIsValid) { + removeStatusUpdateInvalidDevices.add(device); + } + } + + } + } + } + } catch (DeviceManagementDAOException e) { + String msg = "Error occurred while retrieving device list pertaining to the current tenant"; + log.error(msg, e); + throw new DeviceManagementException(msg, e); + } catch (Exception e) { + String msg = "Error occurred in getAllDevices"; + log.error(msg, e); + throw new DeviceManagementException(msg, e); + } finally { + DeviceManagementDAOFactory.closeConnection(); + MetadataManagementDAOFactory.closeConnection(); + } + + if(!removeBillingPeriodInvalidDevices.isEmpty() && removeBillingPeriodInvalidDevices.size() == allDevices.size()) { + allDevicesBilledDateIsValid = false; + paginationResult.setMessage("Invalid bill period."); + } + if(!removeStatusUpdateInvalidDevices.isEmpty() && removeStatusUpdateInvalidDevices.size() == allDevices.size()) { + allDevicesBilledDateIsValid = false; + if (paginationResult.getMessage() != null){ + paginationResult.setMessage(paginationResult.getMessage() + " and no device updates within entered bill period."); + } else { + paginationResult.setMessage("Devices have not been updated within the given period or entered end date comes before the " + + "last billed date."); + } + + } + allDevices.removeAll(removeBillingPeriodInvalidDevices); + allDevices.removeAll(removeStatusUpdateInvalidDevices); + + paginationResult.setBilledDateIsValid(allDevicesBilledDateIsValid); + paginationResult.setData(allDevices); + paginationResult.setTotalCost(Math.round(totalCost * 100.0) / 100.0); + return paginationResult; + } + + @Override + public PaginationResult getAllDevicesBillings(PaginationRequest request, int tenantId, String tenantDomain, Timestamp startDate, Timestamp endDate, boolean generateBill) throws DeviceManagementException { + if (request == null) { + String msg = "Received incomplete pagination request for method getAllDeviceBillings"; + log.error(msg); + throw new DeviceManagementException(msg); + } + + DeviceManagerUtil.validateDeviceListPageSize(request); + PaginationResult paginationResult = new PaginationResult(); + List allDevices; + int count = 0; + + try { + DeviceManagementDAOFactory.beginTransaction(); + allDevices = deviceDAO.getDevices(request, tenantId); + count = deviceDAO.getDeviceCount(request, tenantId); + paginationResult = calculateCost(tenantId, tenantDomain, startDate, endDate, generateBill, allDevices); + + } catch (DeviceManagementDAOException e) { + String msg = "Error occurred while retrieving device bill list pertaining to the current tenant"; + log.error(msg, e); + throw new DeviceManagementException(msg, e); + } catch (Exception e) { + String msg = "Error occurred in getAllDevicesBillings"; + log.error(msg, e); + throw new DeviceManagementException(msg, e); + } + paginationResult.setRecordsFiltered(count); + paginationResult.setRecordsTotal(count); + return paginationResult; + } + + @Override + public PaginationResult createBillingFile(int tenantId, String tenantDomain, Timestamp startDate, Timestamp endDate, boolean generateBill) throws DeviceManagementException { + PaginationResult paginationResult = new PaginationResult(); + List allDevices; + try { + DeviceManagementDAOFactory.beginTransaction(); + allDevices = deviceDAO.getDeviceListWithoutPagination(tenantId); + paginationResult = calculateCost(tenantId, tenantDomain, startDate, endDate, generateBill, allDevices); + + } catch (DeviceManagementDAOException e) { + String msg = "Error occurred while retrieving device bill list without pagination pertaining to the current tenant"; + log.error(msg, e); + throw new DeviceManagementException(msg, e); + } catch (Exception e) { + String msg = "Error occurred in createBillingFile"; + log.error(msg, e); + throw new DeviceManagementException(msg, e); + } + return paginationResult; + } + @Override public PaginationResult getAllDevices(PaginationRequest request, boolean requireDeviceInfo) throws DeviceManagementException { if (request == null) { @@ -1768,14 +1992,15 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv DeviceManagementDAOFactory.closeConnection(); } } + @Override - public List getDeviceStatusHistory(Device device, Date fromDate, Date toDate) throws DeviceManagementException{ + public List getDeviceStatusHistory(Device device, Date fromDate, Date toDate, boolean billingStatus) throws DeviceManagementException { if (log.isDebugEnabled()) { log.debug("get status history of device: " + device.getDeviceIdentifier()); } try { int tenantId = this.getTenantId(); - return deviceStatusDAO.getStatus(device.getId(), tenantId, fromDate, toDate); + return deviceStatusDAO.getStatus(device.getId(), tenantId, fromDate, toDate, billingStatus); } catch (DeviceManagementDAOException e) { DeviceManagementDAOFactory.rollbackTransaction(); String msg = "Error occurred while retrieving status history"; @@ -1789,7 +2014,7 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv } @Override - public List getDeviceCurrentEnrolmentStatusHistory(Device device, Date fromDate, Date toDate) throws DeviceManagementException{ + public List getDeviceCurrentEnrolmentStatusHistory(Device device, Date fromDate, Date toDate) throws DeviceManagementException { if (log.isDebugEnabled()) { log.debug("get status history of device: " + device.getDeviceIdentifier()); } @@ -1818,12 +2043,12 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv } @Override - public List getDeviceStatusHistory(Device device) throws DeviceManagementException{ - return getDeviceStatusHistory(device, null, null); + public List getDeviceStatusHistory(Device device) throws DeviceManagementException { + return getDeviceStatusHistory(device, null, null, false); } @Override - public List getDeviceCurrentEnrolmentStatusHistory(Device device) throws DeviceManagementException{ + public List getDeviceCurrentEnrolmentStatusHistory(Device device) throws DeviceManagementException { return getDeviceCurrentEnrolmentStatusHistory(device, null, null); } @@ -3240,7 +3465,7 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv @Override public List getDeviceLocationInfo(DeviceIdentifier deviceIdentifier, long from, - long to) throws DeviceManagementException { + long to) throws DeviceManagementException { if (log.isDebugEnabled()) { log.debug("Get device location information"); } @@ -4395,12 +4620,12 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv @Override public void triggerCorrectiveActions(String deviceIdentifier, String featureCode, List actions, - List configList) throws DeviceManagementException, DeviceNotFoundException { + List configList) throws DeviceManagementException, DeviceNotFoundException { if (log.isDebugEnabled()) { log.debug("Triggering Corrective action. Device Identifier: " + deviceIdentifier); } - if (StringUtils.isBlank(featureCode)){ + if (StringUtils.isBlank(featureCode)) { String msg = "Found a Blan feature code: " + featureCode; log.error(msg); throw new BadRequestException(msg); @@ -4476,10 +4701,10 @@ public class DeviceManagementProviderServiceImpl implements DeviceManagementProv } @Override - public License getLicenseConfig (String deviceTypeName) throws DeviceManagementException { + public License getLicenseConfig(String deviceTypeName) throws DeviceManagementException { DeviceManagementService deviceManagementService = pluginRepository.getDeviceManagementService(deviceTypeName, - this.getTenantId()); + this.getTenantId()); if (deviceManagementService == null) { String msg = "Device management service loading is failed for the device type: " + deviceTypeName; log.error(msg); diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/conf/mdm-ui-config.xml b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/conf/mdm-ui-config.xml index d93ba4ab7a9..8c0d7bed76a 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/conf/mdm-ui-config.xml +++ b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/conf/mdm-ui-config.xml @@ -24,6 +24,14 @@ 3600 10000 + + false + false + false + false + false + true + analytics_management diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/h2.sql b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/h2.sql index 6372b87e166..c03341d4785 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/h2.sql +++ b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/h2.sql @@ -52,6 +52,17 @@ CREATE TABLE IF NOT EXISTS DM_DEVICE ( CONSTRAINT uk_DM_DEVICE UNIQUE (NAME, DEVICE_TYPE_ID, DEVICE_IDENTIFICATION, TENANT_ID) ); +CREATE TABLE IF NOT EXISTS DM_BILLING ( + INVOICE_ID INTEGER auto_increment NOT NULL, + TENANT_ID INTEGER default 0, + DEVICE_ID INT default NULL, + BILLING_START TIMESTAMP not null, + BILLING_END TIMESTAMP not null, + PRIMARY KEY (INVOICE_ID), + CONSTRAINT FK_DM_BILLING_DM_DEVICE + FOREIGN KEY (DEVICE_ID) REFERENCES DM_DEVICE (ID) +); + CREATE TABLE IF NOT EXISTS DM_DEVICE_PROPERTIES ( DEVICE_TYPE_NAME VARCHAR(300) NOT NULL, DEVICE_IDENTIFICATION VARCHAR(300) NOT NULL, @@ -103,6 +114,7 @@ CREATE TABLE IF NOT EXISTS DM_ENROLMENT ( DATE_OF_ENROLMENT TIMESTAMP DEFAULT NULL, DATE_OF_LAST_UPDATE TIMESTAMP DEFAULT NULL, TENANT_ID INT NOT NULL, + LAST_BILLED_DATE BIGINT DEFAULT 0, PRIMARY KEY (ID), CONSTRAINT fk_dm_device_enrolment FOREIGN KEY (DEVICE_ID) REFERENCES DM_DEVICE (ID) ON DELETE NO ACTION ON UPDATE NO ACTION, diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mssql.sql b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mssql.sql index bd301d6641d..4dc0bba047c 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mssql.sql +++ b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mssql.sql @@ -66,6 +66,18 @@ CREATE TABLE DM_DEVICE ( REFERENCES DM_DEVICE_TYPE (ID) ON DELETE NO ACTION ON UPDATE NO ACTION ); +IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[DM_BILLING]') AND TYPE IN (N'U')) +CREATE TABLE DM_BILLING ( + INVOICE_ID INTEGER IDENTITY(1,1) NOT NULL, + TENANT_ID INTEGER DEFAULT 0, + DEVICE_ID INTEGER DEFAULT NULL, + BILLING_START DATETIME2 NOT NULL, + BILLING_END DATETIME2 NOT NULL, + PRIMARY KEY (INVOICE_ID), + CONSTRAINT FK_DM_BILLING_DM_DEVICE2 FOREIGN KEY (DEVICE_ID) + REFERENCES DM_DEVICE (ID) ON DELETE NO ACTION ON UPDATE NO ACTION +); + IF NOT EXISTS (SELECT * FROM SYS.OBJECTS WHERE OBJECT_ID = OBJECT_ID(N'[DBO].[DM_DEVICE_PROPERTIES]') AND TYPE IN (N'U')) CREATE TABLE DM_DEVICE_PROPERTIES ( DEVICE_TYPE_NAME VARCHAR(300) NOT NULL, @@ -146,6 +158,7 @@ CREATE TABLE DM_ENROLMENT ( DATE_OF_ENROLMENT DATETIME2 DEFAULT NULL, DATE_OF_LAST_UPDATE DATETIME2 DEFAULT NULL, TENANT_ID INTEGER NOT NULL, + LAST_BILLED_DATE BIGINT DEFAULT 0, PRIMARY KEY (ID), CONSTRAINT FK_DM_DEVICE_ENROLMENT FOREIGN KEY (DEVICE_ID) REFERENCES DM_DEVICE (ID) ON DELETE NO ACTION ON UPDATE NO ACTION diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mysql.sql b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mysql.sql index b191a177b77..d967f50e637 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mysql.sql +++ b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/mysql.sql @@ -59,6 +59,17 @@ CREATE TABLE IF NOT EXISTS DM_DEVICE ( REFERENCES DM_DEVICE_TYPE (ID) ON DELETE NO ACTION ON UPDATE NO ACTION )ENGINE = InnoDB; +CREATE TABLE IF NOT EXISTS DM_BILLING ( + INVOICE_ID INTEGER AUTO_INCREMENT NOT NULL, + TENANT_ID INTEGER DEFAULT 0, + DEVICE_ID INTEGER DEFAULT NULL, + BILLING_START TIMESTAMP NOT NULL, + BILLING_END TIMESTAMP NOT NULL, + PRIMARY KEY (INVOICE_ID), + CONSTRAINT fk_DM_BILLING_DM_DEVICE2 FOREIGN KEY (DEVICE_ID) + REFERENCES DM_DEVICE (ID) ON DELETE NO ACTION ON UPDATE NO ACTION +)ENGINE = InnoDB; + CREATE INDEX IDX_DM_DEVICE ON DM_DEVICE(TENANT_ID, DEVICE_TYPE_ID); CREATE INDEX IDX_DM_DEVICE_TYPE_ID_DEVICE_IDENTIFICATION ON DM_DEVICE(TENANT_ID, DEVICE_TYPE_ID,DEVICE_IDENTIFICATION); @@ -118,6 +129,7 @@ CREATE TABLE IF NOT EXISTS DM_ENROLMENT ( DATE_OF_ENROLMENT TIMESTAMP NULL DEFAULT NULL, DATE_OF_LAST_UPDATE TIMESTAMP NULL DEFAULT NULL, TENANT_ID INT NOT NULL, + LAST_BILLED_DATE BIGINT DEFAULT 0, PRIMARY KEY (ID), CONSTRAINT FK_DM_DEVICE_ENROLMENT FOREIGN KEY (DEVICE_ID) REFERENCES DM_DEVICE (ID) ON DELETE NO ACTION ON UPDATE NO ACTION diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/oracle.sql b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/oracle.sql index 878d6095436..7059538ce52 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/oracle.sql +++ b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/oracle.sql @@ -124,6 +124,19 @@ WHEN (NEW.ID IS NULL) END; / +CREATE TABLE DM_BILLING ( + INVOICE_ID NUMBER(10) NOT NULL, + TENANT_ID NUMBER(10) DEFAULT 0, + DEVICE_ID NUMBER(10) DEFAULT NULL, + BILLING_START TIMESTAMP NOT NULL, + BILLING_END TIMESTAMP NOT NULL, + CONSTRAINT PK_DM_BILLING PRIMARY KEY (INVOICE_ID), + CONSTRAINT fk_DM_BILLING_DM_DEVICE2 + FOREIGN KEY (DEVICE_ID) + REFERENCES DM_DEVICE (ID) +) +/ + CREATE TABLE DM_DEVICE_PROPERTIES ( DEVICE_TYPE_NAME VARCHAR2(300) NOT NULL, DEVICE_IDENTIFICATION VARCHAR2(300) NOT NULL, @@ -208,6 +221,7 @@ CREATE TABLE DM_ENROLMENT ( DATE_OF_ENROLMENT TIMESTAMP(0) DEFAULT NULL, DATE_OF_LAST_UPDATE TIMESTAMP(0) DEFAULT NULL, TENANT_ID NUMBER(10) NOT NULL, + LAST_BILLED_DATE BIGINT DEFAULT 0, CONSTRAINT PK_DM_ENROLMENT PRIMARY KEY (ID), CONSTRAINT FK_DM_DEVICE_ENROLMENT FOREIGN KEY (DEVICE_ID) REFERENCES DM_DEVICE (ID) diff --git a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/postgresql.sql b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/postgresql.sql index a9f08b45f86..978cc7344da 100644 --- a/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/postgresql.sql +++ b/features/device-mgt/org.wso2.carbon.device.mgt.basics.feature/src/main/resources/dbscripts/cdm/postgresql.sql @@ -57,6 +57,17 @@ CREATE TABLE IF NOT EXISTS DM_DEVICE ( REFERENCES DM_DEVICE_TYPE (ID) ON DELETE NO ACTION ON UPDATE NO ACTION ); +CREATE TABLE IF NOT EXISTS DM_BILLING ( + INVOICE_ID INTEGER DEFAULT NEXTVAL ('DM_BILLING_seq') NOT NULL, + TENANT_ID INTEGER DEFAULT 0, + DEVICE_ID INTEGER DEFAULT NULL, + BILLING_START TIMESTAMP(0) NOT NULL, + BILLING_END TIMESTAMP(0) NOT NULL, + PRIMARY KEY (INVOICE_ID), + CONSTRAINT fk_DM_BILLING_DM_DEVICE2 FOREIGN KEY (DEVICE_ID) + REFERENCES DM_DEVICE (ID) ON DELETE NO ACTION ON UPDATE NO ACTION + ); + CREATE INDEX IDX_DM_DEVICE ON DM_DEVICE(TENANT_ID, DEVICE_TYPE_ID); CREATE INDEX IDX_DM_DEVICE_TYPE_ID_DEVICE_IDENTIFICATION ON DM_DEVICE(TENANT_ID, DEVICE_TYPE_ID,DEVICE_IDENTIFICATION); @@ -116,6 +127,7 @@ CREATE TABLE IF NOT EXISTS DM_ENROLMENT ( DATE_OF_ENROLMENT TIMESTAMP(0) NULL DEFAULT NULL, DATE_OF_LAST_UPDATE TIMESTAMP(0) NULL DEFAULT NULL, TENANT_ID INTEGER NOT NULL, + LAST_BILLED_DATE BIGINT DEFAULT 0, PRIMARY KEY (ID), CONSTRAINT FK_DM_DEVICE_ENROLMENT FOREIGN KEY (DEVICE_ID) REFERENCES DM_DEVICE (ID) ON DELETE NO ACTION ON UPDATE NO ACTION