Quellcode durchsuchen

fix: 统计模块和其它模块优化

cjwen vor 1 Jahr
Ursprung
Commit
a2ad7c255a
20 geänderte Dateien mit 492 neuen und 41 gelöschten Zeilen
  1. 39 5
      src/main/java/com/ichaoj/ams/controller/AirdropProjectController.java
  2. 10 1
      src/main/java/com/ichaoj/ams/controller/AirdropTaskController.java
  3. 110 21
      src/main/java/com/ichaoj/ams/controller/StatisticsController.java
  4. 12 0
      src/main/java/com/ichaoj/ams/mapper/AmsAddressAccountMapper.java
  5. 14 1
      src/main/java/com/ichaoj/ams/mapper/AmsTradeRecordMapper.java
  6. 28 0
      src/main/java/com/ichaoj/ams/request/airdrop/UpdateProjectStatus.java
  7. 20 0
      src/main/java/com/ichaoj/ams/request/count/DailyCostRequest.java
  8. 25 0
      src/main/java/com/ichaoj/ams/response/address/CountAddressResponse.java
  9. 2 0
      src/main/java/com/ichaoj/ams/response/airdrop/AirdropProjectResponse.java
  10. 22 0
      src/main/java/com/ichaoj/ams/response/count/DailyCostResponse.java
  11. 30 0
      src/main/java/com/ichaoj/ams/response/count/PredictCostResponse.java
  12. 23 0
      src/main/java/com/ichaoj/ams/response/task/TaskProgressResponse.java
  13. 17 2
      src/main/java/com/ichaoj/ams/service/IAmsAddressAccountService.java
  14. 8 0
      src/main/java/com/ichaoj/ams/service/IAmsAirdropProjectService.java
  15. 7 0
      src/main/java/com/ichaoj/ams/service/IAmsTradeRecordService.java
  16. 19 4
      src/main/java/com/ichaoj/ams/service/impl/AmsAddressAccountServiceImpl.java
  17. 81 7
      src/main/java/com/ichaoj/ams/service/impl/AmsAirdropProjectServiceImpl.java
  18. 6 0
      src/main/java/com/ichaoj/ams/service/impl/AmsTradeRecordServiceImpl.java
  19. 10 0
      src/main/resources/mapper/AmsAddressAccountMapper.xml
  20. 9 0
      src/main/resources/mapper/AmsTradeRecordMapper.xml

+ 39 - 5
src/main/java/com/ichaoj/ams/controller/AirdropProjectController.java

@@ -3,10 +3,12 @@ package com.ichaoj.ams.controller;
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.ichaoj.ams.entity.AmsAirdropProject;
 import com.ichaoj.ams.entity.AmsAirdropTask;
 import com.ichaoj.ams.request.airdrop.CreateAirdropProject;
 import com.ichaoj.ams.request.airdrop.PageProjectRequest;
 import com.ichaoj.ams.request.airdrop.UpdateAirdropProject;
+import com.ichaoj.ams.request.airdrop.UpdateProjectStatus;
 import com.ichaoj.ams.response.airdrop.AirdropProjectResponse;
 import com.ichaoj.ams.response.airdrop.ProjectDetailResponse;
 import com.ichaoj.ams.response.task.TaskResponse;
@@ -18,11 +20,16 @@ import com.ichaoj.common.model.PublicPage;
 import com.ichaoj.common.model.PublicResult;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
+import jnr.ffi.annotations.In;
 import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
+
+import static com.ichaoj.ams.constant.AmsConstant.AirdropStatus.ONGOING;
 
 /**
  * <p>
@@ -44,7 +51,7 @@ public class AirdropProjectController {
 
     @PostMapping
     @Operation(summary = "创建空投项目")
-    @AuthResource(true)
+    @AuthResource
     public PublicResult<Object> createAirdropProject(@RequestBody CreateAirdropProject createAirdropProject) {
         airdropProjectService.createAirdropProject(createAirdropProject);
         return PublicResult.success();
@@ -52,15 +59,31 @@ public class AirdropProjectController {
 
     @PutMapping
     @Operation(summary = "修改空投项目")
-    @AuthResource(true)
+    @AuthResource
     public PublicResult<Object> updateAirdropProject(@RequestBody @Validated UpdateAirdropProject updateAirdropProject) {
         airdropProjectService.updateAirdropProject(updateAirdropProject);
         return PublicResult.success();
     }
 
+    @PutMapping("update-status")
+    @Operation(summary = "修改项目状态")
+    @AuthResource
+    public PublicResult<Object> updateProjectStatus(@RequestBody @Validated UpdateProjectStatus projectStatus) {
+        if (projectStatus.getStatus() == null) {
+            throw new ErrorServiceException("状态不能为空");
+        }
+        AmsAirdropProject project = airdropProjectService.getById(projectStatus.getAmsProjectId());
+        if (project == null) {
+            throw new ErrorServiceException("项目id错误");
+        }
+        project.setStatus(projectStatus.getStatus());
+        airdropProjectService.updateById(project);
+        return PublicResult.success();
+    }
+
     @DeleteMapping("/{projectId}")
     @Operation(summary = "删除空投项目")
-    @AuthResource(true)
+    @AuthResource
     public PublicResult<Object> deleteAirdropProject(@PathVariable String projectId) {
         airdropProjectService.removeById(projectId);
         return PublicResult.success();
@@ -74,12 +97,11 @@ public class AirdropProjectController {
         return PublicResult.success(result);
     }
 
-
     @GetMapping("/detail/{projectId}")
     @Operation(summary = "根据项目id查询详情")
     @AuthResource
     public PublicResult<ProjectDetailResponse> getByProjectId(@PathVariable String projectId) {
-        if (StrUtil.isBlank(projectId)){
+        if (StrUtil.isBlank(projectId)) {
             throw new ErrorServiceException("projectId 不能为空");
         }
         ProjectDetailResponse project = BeanUtil.copyProperties(airdropProjectService.getById(projectId), ProjectDetailResponse.class);
@@ -88,4 +110,16 @@ public class AirdropProjectController {
         project.setTasks(taskResponses);
         return PublicResult.success(project);
     }
+
+    @GetMapping("/count/projectNum")
+    @Operation(summary = "统计项目数量")
+    @AuthResource
+    public PublicResult<Map<String, Object>> getProjectNum() {
+        Map<String, Object> map = new HashMap<>(4);
+        map.put("totalCount", airdropProjectService.count());
+        map.put("runningCount", airdropProjectService.count(new LambdaQueryWrapper<AmsAirdropProject>().eq(AmsAirdropProject::getStatus, ONGOING)));
+        return PublicResult.success(map);
+    }
+
+
 }

+ 10 - 1
src/main/java/com/ichaoj/ams/controller/AirdropTaskController.java

@@ -21,6 +21,7 @@ import org.springframework.validation.annotation.Validated;
 import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
+import java.util.List;
 
 /**
  * <p>
@@ -62,7 +63,7 @@ public class AirdropTaskController {
         if (task != null) {
             task.setTaskStatus(statusRequest.getTaskStatus());
             taskService.updateById(task);
-        }else {
+        } else {
             throw new ErrorServiceException("Task Error");
         }
         return PublicResult.success();
@@ -83,4 +84,12 @@ public class AirdropTaskController {
         PublicPage<TaskResponse> result = taskService.pageAirdropProject(taskRequest);
         return PublicResult.success(result);
     }
+
+    @GetMapping("/list")
+    @Operation(summary = "查询任务列表")
+    @AuthResource
+    public PublicResult<List<TaskResponse>> listTask() {
+        List<TaskResponse> result = BeanUtil.copyToList(taskService.list(), TaskResponse.class);
+        return PublicResult.success(result);
+    }
 }

+ 110 - 21
src/main/java/com/ichaoj/ams/controller/StatisticsController.java

@@ -1,22 +1,28 @@
 package com.ichaoj.ams.controller;
 
-import com.ichaoj.ams.service.IAmsAddressAccountService;
-import com.ichaoj.ams.service.IAmsTradeRecordService;
+import cn.hutool.core.date.LocalDateTimeUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.ichaoj.ams.entity.AmsAirdropTask;
+import com.ichaoj.ams.entity.AmsExecuteRecord;
+import com.ichaoj.ams.entity.AmsTradeRecord;
+import com.ichaoj.ams.request.count.DailyCostRequest;
+import com.ichaoj.ams.response.address.CountAddressResponse;
+import com.ichaoj.ams.response.count.DailyCostResponse;
+import com.ichaoj.ams.response.count.PredictCostResponse;
+import com.ichaoj.ams.response.task.TaskProgressResponse;
+import com.ichaoj.ams.service.*;
 import com.ichaoj.common.annotation.AuthResource;
 import com.ichaoj.common.model.PublicResult;
 import com.ichaoj.common.model.PublicUserInfo;
 import com.ichaoj.web.context.SuperWhaleContext;
 import io.swagger.v3.oas.annotations.Operation;
 import io.swagger.v3.oas.annotations.tags.Tag;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestMapping;
-import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.bind.annotation.*;
 
 import javax.annotation.Resource;
 import java.math.BigDecimal;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.time.LocalDateTime;
+import java.util.*;
 
 /**
  * @author : cjwen
@@ -30,35 +36,118 @@ public class StatisticsController {
 
     @Resource
     private IAmsTradeRecordService tradeService;
+    @Resource
+    private IAmsAirdropProjectService projectService;
 
     @Resource
     private IAmsAddressAccountService accountService;
+    @Resource
+    private IAmsAirdropTaskService taskService;
+    @Resource
+    private IAmsExecuteRecordService executeRecordService;
+
+
+    @GetMapping("address-group")
+    @Operation(summary = "地址统计")
+    @AuthResource
+    private PublicResult<List<CountAddressResponse>> getGroupAndWalletNum() {
+        List<String> list = accountService.queryGroupList(0);
+        List<CountAddressResponse> responseList = new ArrayList<>();
+        CountAddressResponse preCount = new CountAddressResponse();
+        preCount.setGroupName("精品号");
+        preCount.setAddressCount(list.size());
+        responseList.add(0, preCount);
+        String userId = SuperWhaleContext.getContext(PublicUserInfo.class).getUserId();
+        List<CountAddressResponse> batchList = accountService.countBatchCount(userId);
+        responseList.addAll(batchList);
+        return PublicResult.success(responseList);
+    }
 
     @GetMapping("daily-cost")
     @Operation(summary = "每日消耗gas和本金")
     @AuthResource
-    public PublicResult<Map<String, Object>> dailyCostStatistics() {
-        Map<String, Object> map = new HashMap<>(5);
-        String userId = SuperWhaleContext.getContext(PublicUserInfo.class).getUserId();
-        List<String> batchAddresses = accountService.queryGroupList(1);
+    public PublicResult<List<DailyCostResponse>> dailyCostStatistics() {
+        List<DailyCostResponse> list = tradeService.dailyCostStatistics();
+        return PublicResult.success(list);
+    }
+
+    @GetMapping("predict-cost")
+    @Operation(summary = "统计预计投入")
+    @AuthResource
+    public PublicResult<PredictCostResponse> predictCostStatistics() {
+        PredictCostResponse response = projectService.predictCostStatistics();
+        return PublicResult.success(response);
+    }
 
+    @GetMapping("count-fee")
+    @Operation(summary = "费用统计")
+    @AuthResource
+    public PublicResult<Map<String, Object>> feeCostStatistics() {
+        Map<String, Object> map = new HashMap<>(5);
+        List<String> batchAddresses = accountService.queryBatchAddress(1);
         // 从链上获取当日gas费用
-        BigDecimal dailyGasCost = getDailyGasCost(userId);
+        BigDecimal dailyGasCost = getGasCost(batchAddresses);
+        map.put("expendGas", dailyGasCost);
         // 从链上获取当日本金消耗量
-//        BigDecimal dailyPrincipalCost = getDailyPrincipalCost(userId);
-        // 总消耗 = gas费用 + 本金消耗
-//        BigDecimal totalCost = dailyGasCost.add(dailyPrincipalCost);
+        BigDecimal dailyPrincipalCost = getPrincipalCost(batchAddresses);
+        // 本金余额
+        map.put("principalBalance", dailyPrincipalCost);
+
+        map.put("predictTotalCost", projectService.list().stream().mapToDouble(p -> Double.parseDouble(p.getEstimatedCost())).sum());
         return PublicResult.success(map);
     }
 
-    private void getGroupAndWalletNum(Map<String, Object> map) {
-        List<String> list = accountService.queryGroupList(0);
-        map.put("premiumCount", list.size());
+    @GetMapping("task-progress")
+    @Operation(summary = "统计任务进度")
+    @AuthResource
+    public PublicResult<List<TaskProgressResponse>> countTaskProgress() {
+        List<TaskProgressResponse> responseList = new ArrayList<>();
+        List<AmsAirdropTask> list = taskService.list();
+        for (AmsAirdropTask task : list) {
+            TaskProgressResponse response = new TaskProgressResponse();
+            Integer planTimes = task.getPlanTimes();
+            response.setTotalCount(planTimes);
+            long count = executeRecordService.count(
+                    new LambdaQueryWrapper<AmsExecuteRecord>()
+                            .eq(AmsExecuteRecord::getTaskId, task.getAmsTaskId())
+                            .eq(AmsExecuteRecord::getExecuteStatus, 1)
+            );
+            response.setFinishCount((int) count);
+            response.setTaskName(task.getTaskName());
+            responseList.add(response);
+        }
+        return PublicResult.success(responseList);
+    }
+
+    private BigDecimal getPrincipalCost(List<String> batchAddresses) {
+        List<AmsTradeRecord> list = getTradeRecordList(batchAddresses);
+        double sumAmount = list.stream().mapToDouble(t -> Double.parseDouble(t.getCurrentBalance())).sum();
+        return BigDecimal.valueOf(sumAmount);
+    }
+
+    private BigDecimal getGasCost(List<String> batchAddresses) {
+        List<AmsTradeRecord> list = getTradeRecordList(batchAddresses);
+        double sumGas = list.stream().mapToDouble(t -> Double.parseDouble(t.getGas())).sum();
+        return BigDecimal.valueOf(sumGas);
+    }
+
 
+    private List<AmsTradeRecord> getTradeRecordList(List<String> batchAddresses) {
+        return tradeService.list(new LambdaQueryWrapper<AmsTradeRecord>()
+                .in(AmsTradeRecord::getAddress, batchAddresses)
+        );
     }
 
-    private BigDecimal getDailyGasCost(String userId) {
-        return BigDecimal.ZERO;
+    private static LocalDateTime getTodayStartTime() {
+        // 获取Calendar实例
+        Calendar cal = Calendar.getInstance();
+        // 获取今天凌晨的日期时间
+        cal.set(Calendar.HOUR_OF_DAY, 0);
+        cal.set(Calendar.MINUTE, 0);
+        cal.set(Calendar.SECOND, 0);
+        cal.set(Calendar.MILLISECOND, 0);
+        Date todayStart = cal.getTime();
+        return LocalDateTimeUtil.of(todayStart);
     }
 
 }

+ 12 - 0
src/main/java/com/ichaoj/ams/mapper/AmsAddressAccountMapper.java

@@ -5,8 +5,12 @@ import com.ichaoj.ams.entity.AmsAddressAccount;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.ichaoj.ams.request.address.PageAddressRequest;
 import com.ichaoj.ams.response.address.AddressResponse;
+import com.ichaoj.ams.response.address.CountAddressResponse;
 import org.apache.ibatis.annotations.Param;
 
+import java.util.List;
+import java.util.Map;
+
 /**
  * <p>
  * 地址管理 Mapper 接口
@@ -26,4 +30,12 @@ public interface AmsAddressAccountMapper extends BaseMapper<AmsAddressAccount> {
      * @return 分页结果
      */
     Page<AddressResponse> pageAddress(Page<AmsAddressAccount> buildPageObj, @Param("request") PageAddressRequest request, @Param("userId") String userId);
+
+    /**
+     * 统计用户批量地址的数量(按地址组名称分组)
+     *
+     * @param userId 用户id
+     * @return 分组地址map
+     */
+    List<CountAddressResponse> countBatchCount(@Param("userId") String userId);
 }

+ 14 - 1
src/main/java/com/ichaoj/ams/mapper/AmsTradeRecordMapper.java

@@ -4,8 +4,11 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ichaoj.ams.entity.AmsTradeRecord;
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
 import com.ichaoj.ams.request.record.PageTradeRecordRequest;
+import com.ichaoj.ams.response.count.DailyCostResponse;
 import com.ichaoj.ams.response.record.TradeRecordResponse;
 
+import java.util.List;
+
 /**
  * <p>
  * 交易 Mapper 接口
@@ -18,9 +21,19 @@ public interface AmsTradeRecordMapper extends BaseMapper<AmsTradeRecord> {
 
     /**
      * 分页查询交易记录
+     *
      * @param buildPageObj 分页对象
-     * @param request 请求参数
+     * @param request      请求参数
      * @return 分页结果
      */
     Page<TradeRecordResponse> pageTradeRecord(Page<AmsTradeRecord> buildPageObj, PageTradeRecordRequest request);
+
+    /**
+     * 统计每日消耗gas和本金
+     *
+     * @param startTime 开始时间
+     * @param endTime   结束时间
+     * @return 统计数据
+     */
+    List<DailyCostResponse> dailyCostStatistics();
 }

+ 28 - 0
src/main/java/com/ichaoj/ams/request/airdrop/UpdateProjectStatus.java

@@ -0,0 +1,28 @@
+package com.ichaoj.ams.request.airdrop;
+
+import com.ichaoj.ams.constant.AmsConstant;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import javax.validation.constraints.NotBlank;
+import java.util.List;
+
+/**
+ * @author : cjwen
+ * @date : 2023/04/26 14:25
+ */
+@Data
+@Schema(title = "修改空投项目")
+public class UpdateProjectStatus {
+
+    @Schema(title = "空投项目Id")
+    @NotBlank(message = "amsProjectId 不能为空")
+    private String amsProjectId;
+
+    /**
+     * 空投状态
+     */
+    private AmsConstant.AirdropStatus status;
+
+}

+ 20 - 0
src/main/java/com/ichaoj/ams/request/count/DailyCostRequest.java

@@ -0,0 +1,20 @@
+package com.ichaoj.ams.request.count;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * @author : cjwen
+ * @date : 2023/05/29 15:13
+ */
+@Data
+@Schema(title = "日常花费统计")
+public class DailyCostRequest {
+
+    private String startTime;
+
+    private String endTime;
+
+}

+ 25 - 0
src/main/java/com/ichaoj/ams/response/address/CountAddressResponse.java

@@ -0,0 +1,25 @@
+package com.ichaoj.ams.response.address;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.time.LocalDateTime;
+
+/**
+ * @author : cjwen
+ * @date : 2023/04/26 18:18
+ */
+@Data
+public class CountAddressResponse {
+
+    /**
+     * 地址组名称
+     */
+    private String groupName;
+
+    /**
+     * 地址数量
+     */
+    private Integer addressCount;
+
+}

+ 2 - 0
src/main/java/com/ichaoj/ams/response/airdrop/AirdropProjectResponse.java

@@ -58,4 +58,6 @@ public class AirdropProjectResponse {
 
     @Schema(title = "任务完成数")
     private long taskFinishCount;
+
+    private BigDecimal totalGas;
 }

+ 22 - 0
src/main/java/com/ichaoj/ams/response/count/DailyCostResponse.java

@@ -0,0 +1,22 @@
+package com.ichaoj.ams.response.count;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+
+/**
+ * @author : cjwen
+ * @date : 2023/05/29 15:13
+ */
+@Data
+@Schema(title = "日常花费统计")
+public class DailyCostResponse {
+
+    private String date;
+
+    private BigDecimal gas;
+
+    private BigDecimal principal;
+
+}

+ 30 - 0
src/main/java/com/ichaoj/ams/response/count/PredictCostResponse.java

@@ -0,0 +1,30 @@
+package com.ichaoj.ams.response.count;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * @author : cjwen
+ * @date : 2023/05/29 15:13
+ */
+@Data
+@Schema(title = "预计投入统计")
+public class PredictCostResponse {
+
+    private List<Predict> predicts;
+
+    private Integer totalCount;
+
+    private BigDecimal totalCost;
+
+    @Data
+    public static class Predict {
+        private String projectName;
+
+        private BigDecimal estimatedCost;
+    }
+
+}

+ 23 - 0
src/main/java/com/ichaoj/ams/response/task/TaskProgressResponse.java

@@ -0,0 +1,23 @@
+package com.ichaoj.ams.response.task;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+/**
+ * @author : cjwen
+ * @date : 2023/05/29 11:58
+ */
+@Data
+@Schema(title = "任务进度统计")
+public class TaskProgressResponse {
+
+    @Schema(title = "任务名称")
+    private String taskName;
+
+    @Schema(title = "任务计划执行总次数")
+    private Integer totalCount;
+
+    @Schema(title = "任务完成次数")
+    private Integer finishCount;
+
+}

+ 17 - 2
src/main/java/com/ichaoj/ams/service/IAmsAddressAccountService.java

@@ -1,11 +1,12 @@
 package com.ichaoj.ams.service;
 
-import com.ichaoj.ams.entity.AmsAddressAccount;
 import com.baomidou.mybatisplus.extension.service.IService;
+import com.ichaoj.ams.entity.AmsAddressAccount;
 import com.ichaoj.ams.request.address.BatchAddressRequest;
 import com.ichaoj.ams.request.address.PageAddressRequest;
 import com.ichaoj.ams.request.address.PremiumAddressRequest;
 import com.ichaoj.ams.response.address.AddressResponse;
+import com.ichaoj.ams.response.address.CountAddressResponse;
 import com.ichaoj.common.model.PublicPage;
 
 import javax.servlet.http.HttpServletResponse;
@@ -62,7 +63,7 @@ public interface IAmsAddressAccountService extends IService<AmsAddressAccount> {
     /**
      * 查询地址组列表
      * @return 地址组列表
-     * @param addressType
+     * @param addressType 地址类型
      */
     List<String> queryGroupList(int addressType);
 
@@ -72,4 +73,18 @@ public interface IAmsAddressAccountService extends IService<AmsAddressAccount> {
      * @return 地址账户
      */
     AmsAddressAccount getByAddress(String address);
+
+    /**
+     * 统计用户批量地址的数量(按地址组名称分组)
+     * @param userId 用户id
+     * @return 统计结果
+     */
+    List<CountAddressResponse> countBatchCount(String userId);
+
+    /**
+     * 查询地址组列表
+     * @return 地址组列表
+     * @param addressType 地址类型
+     */
+    List<String> queryBatchAddress(int addressType);
 }

+ 8 - 0
src/main/java/com/ichaoj/ams/service/IAmsAirdropProjectService.java

@@ -6,6 +6,7 @@ import com.ichaoj.ams.request.airdrop.CreateAirdropProject;
 import com.ichaoj.ams.request.airdrop.PageProjectRequest;
 import com.ichaoj.ams.request.airdrop.UpdateAirdropProject;
 import com.ichaoj.ams.response.airdrop.AirdropProjectResponse;
+import com.ichaoj.ams.response.count.PredictCostResponse;
 import com.ichaoj.common.model.PublicPage;
 
 /**
@@ -36,4 +37,11 @@ public interface IAmsAirdropProjectService extends IService<AmsAirdropProject> {
      * @param updateAirdropProject 修改参数
      */
     void updateAirdropProject(UpdateAirdropProject updateAirdropProject);
+
+    /**
+     * 统计预计花费
+     * @return 统计结果
+     */
+    PredictCostResponse predictCostStatistics();
+
 }

+ 7 - 0
src/main/java/com/ichaoj/ams/service/IAmsTradeRecordService.java

@@ -4,6 +4,7 @@ import com.ichaoj.ams.entity.AmsAddressAccount;
 import com.ichaoj.ams.entity.AmsTradeRecord;
 import com.baomidou.mybatisplus.extension.service.IService;
 import com.ichaoj.ams.request.record.PageTradeRecordRequest;
+import com.ichaoj.ams.response.count.DailyCostResponse;
 import com.ichaoj.ams.response.record.TradeRecordResponse;
 import com.ichaoj.common.model.PublicPage;
 
@@ -44,4 +45,10 @@ public interface IAmsTradeRecordService extends IService<AmsTradeRecord> {
             String amount,
             String maxGas,
             String executeId);
+
+    /**
+     * 统计每日消耗gas和本金
+     * @return 统计数据
+     */
+    List<DailyCostResponse> dailyCostStatistics();
 }

+ 19 - 4
src/main/java/com/ichaoj/ams/service/impl/AmsAddressAccountServiceImpl.java

@@ -15,6 +15,7 @@ import com.ichaoj.ams.request.address.BatchAddressRequest;
 import com.ichaoj.ams.request.address.PageAddressRequest;
 import com.ichaoj.ams.request.address.PremiumAddressRequest;
 import com.ichaoj.ams.response.address.AddressResponse;
+import com.ichaoj.ams.response.address.CountAddressResponse;
 import com.ichaoj.ams.service.IAmsAddressAccountService;
 import com.ichaoj.ams.service.IAmsTradeRecordService;
 import com.ichaoj.common.exception.ErrorServiceException;
@@ -30,10 +31,7 @@ import javax.annotation.Resource;
 import javax.servlet.http.HttpServletResponse;
 import java.io.File;
 import java.time.LocalDateTime;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
+import java.util.*;
 import java.util.stream.Collectors;
 
 import static com.ichaoj.ams.constant.AmsConstant.WALLET_FILE_PATH;
@@ -122,6 +120,23 @@ public class AmsAddressAccountServiceImpl extends SuperWhaleServiceImpl<AmsAddre
         return this.getOne(wrapper);
     }
 
+    @Override
+    public List<CountAddressResponse> countBatchCount(String userId) {
+        if (StrUtil.isBlank(userId)) {
+            userId = SuperWhaleContext.getContext(PublicUserInfo.class).getUserId();
+        }
+        return this.baseMapper.countBatchCount(userId);
+    }
+
+    @Override
+    public List<String> queryBatchAddress(int addressType) {
+        LambdaQueryWrapper<AmsAddressAccount> wrapper = Wrappers.lambdaQuery();
+        wrapper.eq(AmsAddressAccount::getUserId, SuperWhaleContext.getContext(PublicUserInfo.class).getUserId())
+                .eq(addressType >= 0, AmsAddressAccount::getAddressType, addressType)
+                .groupBy(AmsAddressAccount::getAddress);
+        return this.list(wrapper).stream().map(AmsAddressAccount::getAddress).distinct().collect(Collectors.toList());
+    }
+
     /**
      * 添加精品号
      */

+ 81 - 7
src/main/java/com/ichaoj/ams/service/impl/AmsAirdropProjectServiceImpl.java

@@ -2,6 +2,7 @@ package com.ichaoj.ams.service.impl;
 
 import cn.hutool.core.bean.BeanUtil;
 import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.comparator.CompareUtil;
 import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
@@ -9,21 +10,30 @@ import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ichaoj.ams.constant.AmsConstant;
 import com.ichaoj.ams.entity.AmsAirdropProject;
 import com.ichaoj.ams.entity.AmsAirdropTask;
+import com.ichaoj.ams.entity.AmsExecuteRecord;
+import com.ichaoj.ams.entity.AmsTradeRecord;
 import com.ichaoj.ams.mapper.AmsAirdropProjectMapper;
 import com.ichaoj.ams.request.airdrop.CreateAirdropProject;
 import com.ichaoj.ams.request.airdrop.PageProjectRequest;
 import com.ichaoj.ams.request.airdrop.UpdateAirdropProject;
 import com.ichaoj.ams.response.airdrop.AirdropProjectResponse;
+import com.ichaoj.ams.response.count.PredictCostResponse;
 import com.ichaoj.ams.service.IAmsAirdropProjectService;
 import com.ichaoj.ams.service.IAmsAirdropTaskService;
+import com.ichaoj.ams.service.IAmsExecuteRecordService;
+import com.ichaoj.ams.service.IAmsTradeRecordService;
 import com.ichaoj.common.model.PublicPage;
+import com.ichaoj.common.model.PublicUserInfo;
 import com.ichaoj.mybatis.service.SuperWhaleServiceImpl;
+import com.ichaoj.web.context.SuperWhaleContext;
+import org.springframework.context.annotation.Lazy;
 import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
+import java.math.BigDecimal;
 import java.time.LocalDateTime;
 import java.util.List;
+import java.util.stream.Collectors;
 
 /**
  * <p>
@@ -39,6 +49,13 @@ public class AmsAirdropProjectServiceImpl extends SuperWhaleServiceImpl<AmsAirdr
     @Resource
     private IAmsAirdropTaskService taskService;
 
+    @Resource
+    @Lazy
+    private IAmsExecuteRecordService executeRecordService;
+    @Resource
+    @Lazy
+    private IAmsTradeRecordService tradeRecordService;
+
     @Override
     public PublicPage<AirdropProjectResponse> pageAirdropProject(PageProjectRequest projectRequest) {
         LambdaQueryWrapper<AmsAirdropProject> wrapper = Wrappers.lambdaQuery();
@@ -49,13 +66,36 @@ public class AmsAirdropProjectServiceImpl extends SuperWhaleServiceImpl<AmsAirdr
         Page<AmsAirdropProject> result = this.page(this.buildPageObj(projectRequest), wrapper);
         return this.convertPublicPage(result, project -> {
             AirdropProjectResponse response = BeanUtil.copyProperties(project, AirdropProjectResponse.class);
-            long count = taskService.count(new LambdaQueryWrapper<AmsAirdropTask>()
+            List<AmsExecuteRecord> list = executeRecordService.list(
+                    new LambdaQueryWrapper<AmsExecuteRecord>()
+                            .eq(AmsExecuteRecord::getExecuteStatus, 1)
+                            .eq(AmsExecuteRecord::getProjectId, project.getAmsProjectId())
+                            .eq(AmsExecuteRecord::getUserId, SuperWhaleContext.getContext(PublicUserInfo.class).getUserId())
+            );
+            if (CollectionUtil.isNotEmpty(list)) {
+                List<AmsTradeRecord> records = tradeRecordService.listByIds(list.stream().map(AmsExecuteRecord::getExecuteId).collect(Collectors.toList()));
+                double totalGas = records.stream().mapToDouble(t -> Double.parseDouble(t.getGas())).sum();
+                response.setTotalGas(BigDecimal.valueOf(totalGas));
+            } else {
+                response.setTotalGas(BigDecimal.ZERO);
+            }
+            List<AmsAirdropTask> tasks = taskService.list(new LambdaQueryWrapper<AmsAirdropTask>()
                     .eq(AmsAirdropTask::getAirdropProjectId, project.getAmsProjectId()));
-            response.setTaskTotalCount(count);
-            long finishCount = taskService.count(new LambdaQueryWrapper<AmsAirdropTask>()
-                    .eq(AmsAirdropTask::getAirdropProjectId, project.getAmsProjectId())
-                    .eq(AmsAirdropTask::getTaskStatus, 1));
-            response.setTaskFinishCount(finishCount);
+            if (CollectionUtil.isNotEmpty(tasks)) {
+                long sum = tasks.stream().mapToLong(AmsAirdropTask::getPlanTimes).sum();
+                response.setTaskTotalCount(sum);
+                long finishCount = executeRecordService.count(
+                        new LambdaQueryWrapper<AmsExecuteRecord>()
+                                .eq(AmsExecuteRecord::getExecuteStatus, 1)
+                                .in(AmsExecuteRecord::getTaskId, tasks.stream()
+                                        .map(AmsAirdropTask::getAmsTaskId)
+                                        .collect(Collectors.toList()))
+                );
+                response.setTaskFinishCount(finishCount);
+            } else {
+                response.setTaskTotalCount(0);
+                response.setTaskFinishCount(0);
+            }
             return response;
         });
     }
@@ -66,6 +106,14 @@ public class AmsAirdropProjectServiceImpl extends SuperWhaleServiceImpl<AmsAirdr
         project.setCreateTime(LocalDateTime.now());
         project.setStatus(AmsConstant.AirdropStatus.NOT_STARTED);
         this.save(project);
+//        List<String> taskIds = createAirdropProject.getTaskIds();
+//        if (CollectionUtil.isNotEmpty(taskIds)) {
+//            List<AmsAirdropTask> tasks = taskService.listByIds(taskIds)
+//                    .stream()
+//                    .peek(t -> t.setAirdropProjectId(project.getAmsProjectId()))
+//                    .collect(Collectors.toList());
+//            taskService.updateBatchById(tasks);
+//        }
     }
 
     @Override
@@ -73,6 +121,32 @@ public class AmsAirdropProjectServiceImpl extends SuperWhaleServiceImpl<AmsAirdr
         AmsAirdropProject project = BeanUtil.copyProperties(updateAirdropProject, AmsAirdropProject.class);
         project.setUpdateTime(LocalDateTime.now());
         this.updateById(project);
+        List<UpdateAirdropProject.Task> taskList = updateAirdropProject.getTasks();
+        if (CollectionUtil.isEmpty(taskList)) {
+            return;
+        }
+        List<AmsAirdropTask> tasks = taskService.listByIds(taskList.stream().map(UpdateAirdropProject.Task::getTaskId).collect(Collectors.toList()));
+        if (CollectionUtil.isNotEmpty(tasks)) {
+            for (AmsAirdropTask task : tasks) {
+                for (UpdateAirdropProject.Task t : taskList) {
+                    if (task.getAmsTaskId().equals(t.getTaskId())) {
+                        task.setTaskName(t.getTaskName());
+                        taskService.updateById(task);
+                    }
+                }
+            }
+        }
+    }
+
+    @Override
+    public PredictCostResponse predictCostStatistics() {
+        List<AmsAirdropProject> list = this.list();
+        PredictCostResponse response = new PredictCostResponse();
+        response.setTotalCount(list.size());
+        response.setTotalCost(BigDecimal.valueOf(list.stream().mapToDouble(p -> Double.parseDouble(p.getEstimatedCost())).sum()));
+        List<PredictCostResponse.Predict> predicts = BeanUtil.copyToList(list, PredictCostResponse.Predict.class);
+        response.setPredicts(predicts.stream().sorted((p1, p2) -> CompareUtil.compare(p2.getEstimatedCost(), p1.getEstimatedCost())).collect(Collectors.toList()));
+        return response;
     }
 
 }

+ 6 - 0
src/main/java/com/ichaoj/ams/service/impl/AmsTradeRecordServiceImpl.java

@@ -12,6 +12,7 @@ import com.ichaoj.ams.entity.AmsTradeRecord;
 import com.ichaoj.ams.mapper.AmsTradeRecordMapper;
 import com.ichaoj.ams.request.record.CreateTradeRecordRequest;
 import com.ichaoj.ams.request.record.PageTradeRecordRequest;
+import com.ichaoj.ams.response.count.DailyCostResponse;
 import com.ichaoj.ams.response.record.TradeRecordResponse;
 import com.ichaoj.ams.service.IAmsAddressAccountService;
 import com.ichaoj.ams.service.IAmsAirdropTaskService;
@@ -115,6 +116,11 @@ public class AmsTradeRecordServiceImpl extends SuperWhaleServiceImpl<AmsTradeRec
         }
     }
 
+    @Override
+    public List<DailyCostResponse> dailyCostStatistics() {
+        return this.baseMapper.dailyCostStatistics();
+    }
+
     private BigDecimal getCurrenAmount(String amount) {
         return RandomUtil.randomBigDecimal(BigDecimal.ZERO, new BigDecimal(amount));
     }

+ 10 - 0
src/main/resources/mapper/AmsAddressAccountMapper.xml

@@ -43,4 +43,14 @@
             order by a.create_time desc
         </if>
     </select>
+
+    <select id="countBatchCount" resultType="com.ichaoj.ams.response.address.CountAddressResponse">
+        SELECT a.group_name,
+               count(*) addressCount
+        FROM `ams_address_account` a
+        WHERE a.flag = 0
+          and a.user_id = #{userId}
+          AND a.address_type = 1
+        GROUP BY a.group_name
+    </select>
 </mapper>

+ 9 - 0
src/main/resources/mapper/AmsTradeRecordMapper.xml

@@ -28,4 +28,13 @@
         </if>
         ORDER BY tr.create_time DESC
     </select>
+
+    <select id="dailyCostStatistics" resultType="com.ichaoj.ams.response.count.DailyCostResponse">
+        SELECT DATE_FORMAT(create_time, '%m-%d')   `date`,
+               SUM(gas)    AS                       gas,
+               SUM(amount) AS                       principal
+        FROM ams_trade_record
+        WHERE flag = 0
+        GROUP BY `date`;
+    </select>
 </mapper>