This is an automated email from the ASF dual-hosted git repository.

ofuks pushed a commit to branch develop
in repository https://gitbox.apache.org/repos/asf/incubator-dlab.git


The following commit(s) were added to refs/heads/develop by this push:
     new 1759f9e  [DLAB-1714] BE created notification in case project quota is 
exceeded
1759f9e is described below

commit 1759f9eefbf7868381edece6a3eb265267b77f45
Author: Oleh Fuks <olegfuk...@gmail.com>
AuthorDate: Fri Jul 17 18:05:47 2020 +0300

    [DLAB-1714] BE created notification in case project quota is exceeded
---
 .../epam/dlab/backendapi/dao/BaseBillingDAO.java   | 28 +------------
 .../com/epam/dlab/backendapi/dao/BillingDAO.java   |  8 +---
 .../interceptor/BudgetLimitInterceptor.java        |  5 ++-
 .../dlab/backendapi/resources/BillingResource.java |  8 ++++
 .../resources/dto/HealthStatusPageDTO.java         |  4 --
 .../dto/QuotaUsageDTO.java}                        | 22 ++++------
 .../schedulers/CheckProjectQuoteScheduler.java     |  6 +--
 .../dlab/backendapi/service/BillingService.java    | 15 +++++--
 .../service/impl/BillingServiceImpl.java           | 48 +++++++++++++++++++++-
 .../impl/InfrastructureInfoServiceImpl.java        | 11 ++---
 10 files changed, 89 insertions(+), 66 deletions(-)

diff --git 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/BaseBillingDAO.java
 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/BaseBillingDAO.java
index 0e21bba..7975eeb 100644
--- 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/BaseBillingDAO.java
+++ 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/BaseBillingDAO.java
@@ -20,10 +20,8 @@
 package com.epam.dlab.backendapi.dao;
 
 import com.epam.dlab.backendapi.domain.BillingReportLine;
-import com.epam.dlab.backendapi.domain.BudgetDTO;
 import com.epam.dlab.backendapi.resources.dto.BillingFilter;
 import com.epam.dlab.dto.billing.BillingResourceType;
-import com.epam.dlab.exceptions.ResourceNotFoundException;
 import com.google.inject.Inject;
 import com.mongodb.client.model.Aggregates;
 import com.mongodb.client.model.Filters;
@@ -101,14 +99,14 @@ public class BaseBillingDAO extends BaseDAO implements 
BillingDAO {
        }
 
        @Override
-       public Double getProjectCost(String project) {
+       public Double getOverallProjectCost(String project) {
                final List<Bson> pipeline = Arrays.asList(match(eq(PROJECT, 
project)),
                                group(null, sum(TOTAL_FIELD_NAME, COST_FIELD)));
                return aggregateBillingData(pipeline);
        }
 
        @Override
-       public Double getProjectCost(String project, LocalDate date) {
+       public Double getMonthlyProjectCost(String project, LocalDate date) {
                final List<Bson> pipeline = Arrays.asList(match(
                                and(
                                                eq(PROJECT, project),
@@ -143,28 +141,10 @@ public class BaseBillingDAO extends BaseDAO implements 
BillingDAO {
        }
 
        @Override
-       public boolean isProjectQuoteReached(String project) {
-               final boolean monthlyBudget = 
Optional.ofNullable(projectDAO.get(project)
-                               .orElseThrow(projectNotFound())
-                               .getBudget())
-                               .map(BudgetDTO::isMonthlyBudget)
-                               .orElse(Boolean.FALSE);
-               final Double projectCost = monthlyBudget ? 
getProjectCost(project, LocalDate.now()) : getProjectCost(project);
-               return projectDAO.getAllowedBudget(project)
-                               .filter(allowedBudget -> projectCost.intValue() 
!= 0 && allowedBudget <= projectCost)
-                               .isPresent();
-       }
-
-       @Override
        public List<BillingReportLine> findBillingData(String project, String 
endpoint, List<String> resourceNames) {
                return find(BILLING, and(eq(PROJECT, project), eq(ENDPOINT, 
endpoint), in(RESOURCE_NAME, resourceNames)), BillingReportLine.class);
        }
 
-       @Override
-       public int getBillingProjectQuoteUsed(String project) {
-               return toPercentage(() -> projectDAO.getAllowedBudget(project), 
getProjectCost(project));
-       }
-
        public List<BillingReportLine> aggregateBillingData(BillingFilter 
filter) {
                List<Bson> pipeline = new ArrayList<>();
                List<Bson> matchCriteria = matchCriteria(filter);
@@ -262,8 +242,4 @@ public class BaseBillingDAO extends BaseDAO implements 
BillingDAO {
                                .currency(id.getString(CURRENCY))
                                .build();
        }
-
-       private Supplier<ResourceNotFoundException> projectNotFound() {
-               return () -> new ResourceNotFoundException("Project with passed 
name not found");
-       }
 }
diff --git 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/BillingDAO.java
 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/BillingDAO.java
index da1c9a7..088c319 100644
--- 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/BillingDAO.java
+++ 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/dao/BillingDAO.java
@@ -29,22 +29,18 @@ public interface BillingDAO {
 
        Double getUserCost(String user);
 
-       Double getProjectCost(String project);
+       Double getOverallProjectCost(String project);
 
-       Double getProjectCost(String project, LocalDate date);
+       Double getMonthlyProjectCost(String project, LocalDate date);
 
        int getBillingQuoteUsed();
 
        int getBillingUserQuoteUsed(String user);
 
-       int getBillingProjectQuoteUsed(String project);
-
        boolean isBillingQuoteReached();
 
        boolean isUserQuoteReached(String user);
 
-       boolean isProjectQuoteReached(String project);
-
        List<BillingReportLine> findBillingData(String project, String 
endpoint, List<String> resourceNames);
 
        List<BillingReportLine> aggregateBillingData(BillingFilter filter);
diff --git 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/interceptor/BudgetLimitInterceptor.java
 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/interceptor/BudgetLimitInterceptor.java
index 43fdaf6..ce32e10 100644
--- 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/interceptor/BudgetLimitInterceptor.java
+++ 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/interceptor/BudgetLimitInterceptor.java
@@ -22,6 +22,7 @@ package com.epam.dlab.backendapi.interceptor;
 import com.epam.dlab.auth.UserInfo;
 import com.epam.dlab.backendapi.annotation.Project;
 import com.epam.dlab.backendapi.dao.BillingDAO;
+import com.epam.dlab.backendapi.service.BillingService;
 import com.epam.dlab.exceptions.ResourceQuoteReachedException;
 import com.google.inject.Inject;
 import lombok.extern.slf4j.Slf4j;
@@ -38,6 +39,8 @@ import java.util.stream.IntStream;
 public class BudgetLimitInterceptor implements MethodInterceptor {
        @Inject
        private BillingDAO billingDAO;
+       @Inject
+       private BillingService billingService;
 
        @Override
        public Object invoke(MethodInvocation mi) throws Throwable {
@@ -66,7 +69,7 @@ public class BudgetLimitInterceptor implements 
MethodInterceptor {
                                .filter(i -> 
Objects.nonNull(parameters[i].getAnnotation(Project.class)))
                                .mapToObj(i -> (String) mi.getArguments()[i])
                                .findAny()
-                               .map(billingDAO::isProjectQuoteReached)
+                               .map(billingService::isProjectQuoteReached)
                                .orElse(Boolean.FALSE);
        }
 }
diff --git 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/BillingResource.java
 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/BillingResource.java
index 1916a38..a03edb3 100644
--- 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/BillingResource.java
+++ 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/BillingResource.java
@@ -28,6 +28,7 @@ import io.dropwizard.auth.Auth;
 import javax.validation.Valid;
 import javax.validation.constraints.NotNull;
 import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
 import javax.ws.rs.POST;
 import javax.ws.rs.Path;
 import javax.ws.rs.Produces;
@@ -46,6 +47,13 @@ public class BillingResource {
         this.billingService = billingService;
     }
 
+    @GET
+    @Path("/quota")
+    @Produces(MediaType.APPLICATION_JSON)
+    public Response getQuota(@Auth UserInfo userInfo) {
+        return Response.ok(billingService.getQuotas(userInfo)).build();
+    }
+
     @POST
     @Path("/report")
     @Produces(MediaType.APPLICATION_JSON)
diff --git 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/dto/HealthStatusPageDTO.java
 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/dto/HealthStatusPageDTO.java
index 642dd06..73fd421 100644
--- 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/dto/HealthStatusPageDTO.java
+++ 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/dto/HealthStatusPageDTO.java
@@ -44,10 +44,6 @@ public class HealthStatusPageDTO {
        @JsonProperty
        private boolean projectAdmin;
        @JsonProperty
-       private int billingQuoteUsed;
-       @JsonProperty
-       private int billingUserQuoteUsed;
-       @JsonProperty
        private boolean projectAssigned;
        @JsonProperty
        private BucketBrowser bucketBrowser;
diff --git 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/BillingService.java
 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/dto/QuotaUsageDTO.java
similarity index 58%
copy from 
services/self-service/src/main/java/com/epam/dlab/backendapi/service/BillingService.java
copy to 
services/self-service/src/main/java/com/epam/dlab/backendapi/resources/dto/QuotaUsageDTO.java
index b76b141..e611091 100644
--- 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/BillingService.java
+++ 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/resources/dto/QuotaUsageDTO.java
@@ -17,20 +17,16 @@
  * under the License.
  */
 
-package com.epam.dlab.backendapi.service;
+package com.epam.dlab.backendapi.resources.dto;
 
-import com.epam.dlab.auth.UserInfo;
-import com.epam.dlab.backendapi.domain.BillingReport;
-import com.epam.dlab.backendapi.resources.dto.BillingFilter;
+import lombok.Builder;
+import lombok.Data;
 
-import java.util.List;
+import java.util.Map;
 
-public interface BillingService {
-    BillingReport getBillingReport(UserInfo userInfo, BillingFilter filter);
-
-    String downloadReport(UserInfo userInfo, BillingFilter filter);
-
-    BillingReport getExploratoryBillingData(String project, String endpoint, 
String exploratoryName, List<String> compNames);
-
-    void updateRemoteBillingData(UserInfo userInfo);
+@Data
+@Builder
+public class QuotaUsageDTO {
+       private int totalQuotaUsed;
+       private Map<String, Integer> projectQuotas;
 }
diff --git 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/schedulers/CheckProjectQuoteScheduler.java
 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/schedulers/CheckProjectQuoteScheduler.java
index 030c10d..2dc499f 100644
--- 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/schedulers/CheckProjectQuoteScheduler.java
+++ 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/schedulers/CheckProjectQuoteScheduler.java
@@ -19,9 +19,9 @@
 
 package com.epam.dlab.backendapi.schedulers;
 
-import com.epam.dlab.backendapi.dao.BillingDAO;
 import com.epam.dlab.backendapi.domain.ProjectDTO;
 import com.epam.dlab.backendapi.schedulers.internal.Scheduled;
+import com.epam.dlab.backendapi.service.BillingService;
 import com.epam.dlab.backendapi.service.EnvironmentService;
 import com.epam.dlab.backendapi.service.ProjectService;
 import com.google.inject.Inject;
@@ -34,7 +34,7 @@ import org.quartz.JobExecutionContext;
 public class CheckProjectQuoteScheduler implements Job {
 
        @Inject
-       private BillingDAO billingDAO;
+       private BillingService billingService;
        @Inject
        private EnvironmentService environmentService;
        @Inject
@@ -45,7 +45,7 @@ public class CheckProjectQuoteScheduler implements Job {
                projectService.getProjects()
                                .stream()
                                .map(ProjectDTO::getName)
-                               .filter(billingDAO::isProjectQuoteReached)
+                               .filter(billingService::isProjectQuoteReached)
                                .peek(p -> log.debug("Stopping {} project env 
because of reaching user billing quote", p))
                                
.forEach(environmentService::stopProjectEnvironment);
        }
diff --git 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/BillingService.java
 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/BillingService.java
index b76b141..7291cc7 100644
--- 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/BillingService.java
+++ 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/BillingService.java
@@ -22,15 +22,22 @@ package com.epam.dlab.backendapi.service;
 import com.epam.dlab.auth.UserInfo;
 import com.epam.dlab.backendapi.domain.BillingReport;
 import com.epam.dlab.backendapi.resources.dto.BillingFilter;
+import com.epam.dlab.backendapi.resources.dto.QuotaUsageDTO;
 
 import java.util.List;
 
 public interface BillingService {
-    BillingReport getBillingReport(UserInfo userInfo, BillingFilter filter);
+       BillingReport getBillingReport(UserInfo userInfo, BillingFilter filter);
 
-    String downloadReport(UserInfo userInfo, BillingFilter filter);
+       String downloadReport(UserInfo userInfo, BillingFilter filter);
 
-    BillingReport getExploratoryBillingData(String project, String endpoint, 
String exploratoryName, List<String> compNames);
+       BillingReport getExploratoryBillingData(String project, String 
endpoint, String exploratoryName, List<String> compNames);
 
-    void updateRemoteBillingData(UserInfo userInfo);
+       void updateRemoteBillingData(UserInfo userInfo);
+
+       QuotaUsageDTO getQuotas(UserInfo userInfo);
+
+       boolean isProjectQuoteReached(String project);
+
+       int getBillingProjectQuoteUsed(String project);
 }
diff --git 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/BillingServiceImpl.java
 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/BillingServiceImpl.java
index c0b9aa2..2bcf644 100644
--- 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/BillingServiceImpl.java
+++ 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/BillingServiceImpl.java
@@ -23,12 +23,15 @@ import com.epam.dlab.auth.UserInfo;
 import com.epam.dlab.backendapi.conf.SelfServiceApplicationConfiguration;
 import com.epam.dlab.backendapi.dao.BillingDAO;
 import com.epam.dlab.backendapi.dao.ImageExploratoryDao;
+import com.epam.dlab.backendapi.dao.ProjectDAO;
 import com.epam.dlab.backendapi.domain.BillingReport;
 import com.epam.dlab.backendapi.domain.BillingReportLine;
+import com.epam.dlab.backendapi.domain.BudgetDTO;
 import com.epam.dlab.backendapi.domain.EndpointDTO;
 import com.epam.dlab.backendapi.domain.ProjectDTO;
 import com.epam.dlab.backendapi.domain.ProjectEndpointDTO;
 import com.epam.dlab.backendapi.resources.dto.BillingFilter;
+import com.epam.dlab.backendapi.resources.dto.QuotaUsageDTO;
 import com.epam.dlab.backendapi.roles.RoleType;
 import com.epam.dlab.backendapi.roles.UserRoles;
 import com.epam.dlab.backendapi.service.BillingService;
@@ -63,7 +66,9 @@ import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Optional;
 import java.util.Set;
+import java.util.function.Supplier;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
@@ -73,6 +78,7 @@ public class BillingServiceImpl implements BillingService {
     private static final String USAGE_DATE_FORMAT = "yyyy-MM";
 
     private final ProjectService projectService;
+    private final ProjectDAO projectDAO;
     private final EndpointService endpointService;
     private final ExploratoryService exploratoryService;
     private final SelfServiceApplicationConfiguration configuration;
@@ -82,11 +88,12 @@ public class BillingServiceImpl implements BillingService {
     private final String sbn;
 
     @Inject
-    public BillingServiceImpl(ProjectService projectService, EndpointService 
endpointService,
+    public BillingServiceImpl(ProjectService projectService, ProjectDAO 
projectDAO, EndpointService endpointService,
                               ExploratoryService exploratoryService, 
SelfServiceApplicationConfiguration configuration,
                               @Named(ServiceConsts.BILLING_SERVICE_NAME) 
RESTService provisioningService, ImageExploratoryDao imageExploratoryDao,
                               BillingDAO billingDAO) {
         this.projectService = projectService;
+        this.projectDAO = projectDAO;
         this.endpointService = endpointService;
         this.exploratoryService = exploratoryService;
         this.configuration = configuration;
@@ -176,6 +183,38 @@ public class BillingServiceImpl implements BillingService {
         });
     }
 
+    @Override
+    public QuotaUsageDTO getQuotas(UserInfo userInfo) {
+        int totalQuota = billingDAO.getBillingQuoteUsed();
+        Map<String, Integer> projectQuotas = 
projectService.getProjects(userInfo)
+                .stream()
+                .collect(Collectors.toMap(ProjectDTO::getName, p -> 
getBillingProjectQuoteUsed(p.getName())));
+        return QuotaUsageDTO.builder()
+                .totalQuotaUsed(totalQuota)
+                .projectQuotas(projectQuotas)
+                .build();
+    }
+
+    @Override
+    public boolean isProjectQuoteReached(String project) {
+        final Double projectCost = getProjectCost(project);
+        return projectDAO.getAllowedBudget(project)
+                .filter(allowedBudget -> projectCost.intValue() != 0 && 
allowedBudget <= projectCost)
+                .isPresent();
+    }
+
+    @Override
+    public int getBillingProjectQuoteUsed(String project) {
+        return toPercentage(() -> projectDAO.getAllowedBudget(project), 
getProjectCost(project));
+    }
+
+    private Double getProjectCost(String project) {
+        final boolean monthlyBudget = 
Optional.ofNullable(projectService.get(project).getBudget())
+                .map(BudgetDTO::isMonthlyBudget)
+                .orElse(Boolean.FALSE);
+        return monthlyBudget ? billingDAO.getMonthlyProjectCost(project, 
LocalDate.now()) : billingDAO.getOverallProjectCost(project);
+    }
+
     private Map<String, BillingReportLine> getBillableResources() {
         Set<ProjectDTO> projects = new HashSet<>(projectService.getProjects());
         final Stream<BillingReportLine> ssnBillingDataStream = 
BillingUtils.ssnBillingDataStream(sbn);
@@ -341,4 +380,11 @@ public class BillingServiceImpl implements BillingService {
                 .exploratoryName(billingReportLine.getExploratoryName())
                 .build();
     }
+
+    private Integer toPercentage(Supplier<Optional<Integer>> allowedBudget, 
Double totalCost) {
+        return allowedBudget.get()
+                .map(userBudget -> (totalCost * 100) / userBudget)
+                .map(Double::intValue)
+                .orElse(BigDecimal.ZERO.intValue());
+    }
 }
diff --git 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/InfrastructureInfoServiceImpl.java
 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/InfrastructureInfoServiceImpl.java
index 475f2db..98c2f6d 100644
--- 
a/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/InfrastructureInfoServiceImpl.java
+++ 
b/services/self-service/src/main/java/com/epam/dlab/backendapi/service/impl/InfrastructureInfoServiceImpl.java
@@ -21,7 +21,6 @@ package com.epam.dlab.backendapi.service.impl;
 
 import com.epam.dlab.auth.UserInfo;
 import com.epam.dlab.backendapi.conf.SelfServiceApplicationConfiguration;
-import com.epam.dlab.backendapi.dao.BillingDAO;
 import com.epam.dlab.backendapi.dao.ExploratoryDAO;
 import com.epam.dlab.backendapi.domain.BillingReport;
 import com.epam.dlab.backendapi.domain.EndpointDTO;
@@ -65,18 +64,16 @@ public class InfrastructureInfoServiceImpl implements 
InfrastructureInfoService
 
        private final ExploratoryDAO expDAO;
        private final SelfServiceApplicationConfiguration configuration;
-       private final BillingDAO billingDAO;
        private final ProjectService projectService;
        private final EndpointService endpointService;
        private final BillingService billingService;
 
        @Inject
        public InfrastructureInfoServiceImpl(ExploratoryDAO expDAO, 
SelfServiceApplicationConfiguration configuration,
-                                                                               
 BillingDAO billingDAO, ProjectService projectService, EndpointService 
endpointService,
-                                                                               
 BillingService billingService) {
+                                            ProjectService projectService, 
EndpointService endpointService,
+                                            BillingService billingService) {
                this.expDAO = expDAO;
                this.configuration = configuration;
-               this.billingDAO = billingDAO;
                this.projectService = projectService;
                this.endpointService = endpointService;
                this.billingService = billingService;
@@ -91,7 +88,7 @@ public class InfrastructureInfoServiceImpl implements 
InfrastructureInfoService
                                        .stream()
                                        .map(p -> {
                                                List<UserInstanceDTO> 
exploratories = expDAO.findExploratories(user.getName(), p.getName());
-                                               return new 
ProjectInfrastructureInfo(p.getName(), 
billingDAO.getBillingProjectQuoteUsed(p.getName()),
+                                               return new 
ProjectInfrastructureInfo(p.getName(), 
billingService.getBillingProjectQuoteUsed(p.getName()),
                                                                
getSharedInfo(p.getName()), exploratories, 
getExploratoryBillingData(exploratories),
                                                                
getEndpoints(allEndpoints, p));
                                        })
@@ -115,8 +112,6 @@ public class InfrastructureInfoServiceImpl implements 
InfrastructureInfoService
                                        
.projectAdmin(UserRoles.isProjectAdmin(userInfo))
                                        .admin(UserRoles.isAdmin(userInfo))
                                        
.projectAssigned(projectService.isAnyProjectAssigned(userInfo))
-                                       
.billingQuoteUsed(billingDAO.getBillingQuoteUsed())
-                                       
.billingUserQuoteUsed(billingDAO.getBillingUserQuoteUsed(user))
                                        
.bucketBrowser(HealthStatusPageDTO.BucketBrowser.builder()
                                                        
.view(checkAccess(userInfo, PERMISSION_VIEW))
                                                        
.upload(checkAccess(userInfo, PERMISSION_UPLOAD))


---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscr...@dlab.apache.org
For additional commands, e-mail: commits-h...@dlab.apache.org

Reply via email to