2 Incheckningar d03c9e6055 ... 515583e9d9

Upphovsman SHA1 Meddelande Datum
  cjwen 515583e9d9 Merge branch 'master' of https://git.ichaoj.com/MorningWhale/ams-backend 1 år sedan
  cjwen d41540741f fix: ams 优化 1 år sedan

+ 5 - 0
pom.xml

@@ -90,6 +90,11 @@
             <artifactId>poi-ooxml-schemas</artifactId>
             <version>3.17</version>
         </dependency>
+
+        <dependency>
+            <groupId>com.ichaoj</groupId>
+            <artifactId>super-whale-redisson-starter</artifactId>
+        </dependency>
     </dependencies>
 
     <build>

+ 1 - 3
src/main/java/com/ichaoj/ams/common/util/PoiUtils.java

@@ -5,12 +5,10 @@ import cn.hutool.core.io.IoUtil;
 import cn.hutool.poi.excel.ExcelUtil;
 import cn.hutool.poi.excel.ExcelWriter;
 import com.ichaoj.ams.response.statistics.SheetDTO;
-import org.apache.poi.ss.usermodel.Workbook;
-import org.apache.poi.util.IOUtils;
 
 import javax.servlet.ServletOutputStream;
 import javax.servlet.http.HttpServletResponse;
-import java.io.*;
+import java.io.IOException;
 import java.net.URLEncoder;
 import java.util.List;
 

+ 0 - 9
src/main/java/com/ichaoj/ams/controller/StatisticsController.java

@@ -185,15 +185,6 @@ public class StatisticsController {
         }
     }
 
-    private File createProjectExcelFile() {
-        return null;
-    }
-
-    private File createProjectExcelFile(DailyCostRequest dailyCostRequest) {
-
-        return null;
-    }
-
     private BigDecimal getPrincipalCost(List<String> batchAddresses) {
         List<AmsTradeRecord> list = getTradeRecordList(batchAddresses);
         double sumAmount = list.stream().mapToDouble(t -> Double.parseDouble(t.getCurrentBalance())).sum();

+ 15 - 0
src/main/java/com/ichaoj/ams/mapper/AmsExecuteRecordMapper.java

@@ -1,7 +1,11 @@
 package com.ichaoj.ams.mapper;
 
 import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ichaoj.ams.entity.AmsExecuteRecord;
+import com.ichaoj.ams.request.execute.PageExecuteRequest;
+import com.ichaoj.ams.response.execute.ExecuteResponse;
+import org.apache.ibatis.annotations.Param;
 
 /**
  * <p>
@@ -13,4 +17,15 @@ import com.ichaoj.ams.entity.AmsExecuteRecord;
  */
 public interface AmsExecuteRecordMapper extends BaseMapper<AmsExecuteRecord> {
 
+    /**
+     * 分页查询执行
+     *
+     * @param buildPageObj 分页对象
+     * @param request      请求参数
+     * @param userId       用户id
+     * @return 分页结果
+     */
+    Page<ExecuteResponse> pageExecute(Page<AmsExecuteRecord> buildPageObj,
+                                      @Param("request") PageExecuteRequest request,
+                                      @Param("userId") String userId);
 }

+ 8 - 0
src/main/java/com/ichaoj/ams/mapper/AmsTradeRecordMapper.java

@@ -7,6 +7,7 @@ import com.ichaoj.ams.request.record.PageTradeRecordRequest;
 import com.ichaoj.ams.response.statistics.DailyCostResponse;
 import com.ichaoj.ams.response.record.TradeRecordResponse;
 import com.ichaoj.ams.response.statistics.ExportResponse;
+import org.apache.ibatis.annotations.Param;
 
 import java.util.List;
 
@@ -42,4 +43,11 @@ public interface AmsTradeRecordMapper extends BaseMapper<AmsTradeRecord> {
      * @return 报表数据
      */
     List<ExportResponse> getExportData(String userId);
+
+    /**
+     * 根据用户id查询用户投入列表
+     * @param userId 用户
+     * @return 列表
+     */
+    List<TradeRecordResponse> listByUserId(@Param("userId") String userId);
 }

+ 5 - 0
src/main/java/com/ichaoj/ams/request/task/CreateAirdropTask.java

@@ -24,6 +24,11 @@ public class CreateAirdropTask {
      */
     private String taskName;
 
+    /**
+     * 计划任务执行次数
+     */
+    private Integer planTimes;
+
     /**
      * 合约地址
      */

+ 17 - 1
src/main/java/com/ichaoj/ams/response/execute/ExecuteResponse.java

@@ -16,10 +16,16 @@ import java.util.List;
 public class ExecuteResponse {
 
     private String executeId;
+
     /**
      * 交互名称
      */
-    private Integer executeName;
+    private Integer executeTimes;
+
+    /**
+     * 空投项目id
+     */
+    private String projectId;
 
     /**
      * 任务id
@@ -60,12 +66,22 @@ public class ExecuteResponse {
      * 交互金额
      */
     private String amount;
+    private String totalAmount;
 
     /**
      * 最大gas
      */
     private String maxGas;
 
+    private String totalGas;
+
+    private String totalCount;
+
+    /**
+     * 执行状态;是否完成(0否,1是)
+     */
+    private Integer executeStatus;
+
     /**
      * 创建时间
      */

+ 4 - 0
src/main/java/com/ichaoj/ams/response/statistics/PredictCostResponse.java

@@ -19,6 +19,10 @@ public class PredictCostResponse {
     private Integer totalCount;
 
     private BigDecimal totalCost;
+    /**
+     * 实际投入
+     */
+    private BigDecimal actualCost;
 
     @Data
     public static class Predict {

+ 21 - 2
src/main/java/com/ichaoj/ams/response/task/TaskResponse.java

@@ -4,8 +4,6 @@ import com.ichaoj.ams.constant.AmsConstant;
 import io.swagger.v3.oas.annotations.media.Schema;
 import lombok.Data;
 
-import java.time.LocalDateTime;
-
 /**
  * @author : cjwen
  * @date : 2023/05/17 14:57
@@ -53,8 +51,15 @@ public class TaskResponse {
      */
     private String projectName;
 
+    /**
+     * 项目相关url
+     */
+    private String projectUrl;
+
     private Integer executeTimes;
 
+    private String executeId;
+
     /**
      * 执行状态;是否完成(0否,1是)
      */
@@ -62,5 +67,19 @@ public class TaskResponse {
 
     private String lastExecuteTime;
 
+    private String groupName;
+    private String maxGas;
+
+    /**
+     * 时间间隔最小分钟数
+     */
+    private Integer intervalMin;
+
+    /**
+     * 时间间隔最大分钟数
+     */
+    private Integer intervalMax;
+
+
 
 }

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

@@ -59,4 +59,10 @@ public interface IAmsTradeRecordService extends IService<AmsTradeRecord> {
      */
     List<ExportResponse> getExportData();
 
+    /**
+     * 根据用户id查询用户投入列表
+     * @param userId 用户
+     * @return 列表
+     */
+    List<TradeRecordResponse> listByUserId(String userId);
 }

+ 5 - 0
src/main/java/com/ichaoj/ams/service/impl/AmsAirdropProjectServiceImpl.java

@@ -3,6 +3,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.math.MathUtil;
 import cn.hutool.core.util.StrUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
@@ -17,6 +18,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.record.TradeRecordResponse;
 import com.ichaoj.ams.response.statistics.PredictCostResponse;
 import com.ichaoj.ams.service.IAmsAirdropProjectService;
 import com.ichaoj.ams.service.IAmsAirdropTaskService;
@@ -146,6 +148,9 @@ public class AmsAirdropProjectServiceImpl extends SuperWhaleServiceImpl<AmsAirdr
         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()));
+        List<TradeRecordResponse> tradeList = tradeRecordService.listByUserId(SuperWhaleContext.getContext(PublicUserInfo.class).getUserId());
+
+        response.setActualCost(BigDecimal.valueOf(tradeList.stream().mapToDouble(t -> Double.sum(Double.parseDouble(t.getGas()), Double.parseDouble(t.getAmount()))).sum()));
         return response;
     }
 

+ 8 - 8
src/main/java/com/ichaoj/ams/service/impl/AmsExecuteRecordServiceImpl.java

@@ -55,13 +55,14 @@ public class AmsExecuteRecordServiceImpl extends SuperWhaleServiceImpl<AmsExecut
 
     @Override
     public PublicPage<ExecuteResponse> pageExecute(PageExecuteRequest executeRequest) {
-        LambdaQueryWrapper<AmsExecuteRecord> wrapper = Wrappers.lambdaQuery();
-        wrapper
-                .eq(StrUtil.isNotBlank(executeRequest.getQueryValue()), AmsExecuteRecord::getExecuteId, executeRequest.getQueryValue())
-                .or(w -> w.like(StrUtil.isNotBlank(executeRequest.getQueryValue()), AmsExecuteRecord::getGroupName, executeRequest.getQueryValue())
-                        .or().like(StrUtil.isNotBlank(executeRequest.getQueryValue()), AmsExecuteRecord::getTaskId, executeRequest.getQueryValue()))
-                .orderByDesc(AmsExecuteRecord::getCreateTime);
-        Page<AmsExecuteRecord> result = this.page(this.buildPageObj(executeRequest), wrapper);
+//        LambdaQueryWrapper<AmsExecuteRecord> wrapper = Wrappers.lambdaQuery();
+//        wrapper
+//                .eq(StrUtil.isNotBlank(executeRequest.getQueryValue()), AmsExecuteRecord::getExecuteId, executeRequest.getQueryValue())
+//                .or(w -> w.like(StrUtil.isNotBlank(executeRequest.getQueryValue()), AmsExecuteRecord::getGroupName, executeRequest.getQueryValue())
+//                        .or().like(StrUtil.isNotBlank(executeRequest.getQueryValue()), AmsExecuteRecord::getTaskId, executeRequest.getQueryValue()))
+//                .orderByDesc(AmsExecuteRecord::getCreateTime);
+
+        Page<ExecuteResponse> result = this.baseMapper.pageExecute(this.buildPageObj(executeRequest), executeRequest, SuperWhaleContext.getContext(PublicUserInfo.class).getUserId());
         return this.convertPublicPage(result, s -> BeanUtil.copyProperties(s, ExecuteResponse.class));
     }
 
@@ -156,7 +157,6 @@ public class AmsExecuteRecordServiceImpl extends SuperWhaleServiceImpl<AmsExecut
     public void scanExecuteStatus() {
         List<AmsExecuteRecord> list = this.list();
         for (AmsExecuteRecord executeRecord : list) {
-            // 验证用户执行的状态
             String executeId = executeRecord.getExecuteId();
             String userId = executeRecord.getUserId();
             String groupName = executeRecord.getGroupName();

+ 77 - 34
src/main/java/com/ichaoj/ams/service/impl/AmsTradeRecordServiceImpl.java

@@ -1,11 +1,17 @@
 package com.ichaoj.ams.service.impl;
 
 import cn.hutool.core.bean.BeanUtil;
+import cn.hutool.core.collection.CollectionUtil;
+import cn.hutool.core.date.DateTime;
+import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.date.LocalDateTimeUtil;
+import cn.hutool.core.thread.ThreadUtil;
 import cn.hutool.core.util.IdUtil;
 import cn.hutool.core.util.RandomUtil;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.ichaoj.ams.entity.AmsAddressAccount;
+import com.ichaoj.ams.entity.AmsExecuteRecord;
 import com.ichaoj.ams.entity.AmsTradeRecord;
 import com.ichaoj.ams.mapper.AmsTradeRecordMapper;
 import com.ichaoj.ams.request.record.CreateTradeRecordRequest;
@@ -21,6 +27,7 @@ import com.ichaoj.mybatis.service.SuperWhaleServiceImpl;
 import com.ichaoj.web.context.SuperWhaleContext;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.context.annotation.Lazy;
+import org.springframework.scheduling.annotation.Scheduled;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
@@ -65,49 +72,66 @@ public class AmsTradeRecordServiceImpl extends SuperWhaleServiceImpl<AmsTradeRec
         for (String address : addresses) {
             addressMap.put(address, false);
         }
-
-        doTrans(intervalMin, intervalMax, amount, maxGas, executeId, addressMap, set, addresses);
+        prepareTrans(intervalMin, intervalMax, amount, maxGas, executeId, addressMap, set, addresses);
     }
 
     @Transactional(rollbackFor = Exception.class)
-    protected void doTrans(Integer intervalMin, Integer intervalMax, String amount, String maxGas, String executeId, Map<String, Boolean> addressMap, Set<String> set, List<String> addresses) {
-        while (set.size() < addresses.size() - 1) {
-            for (int i = 0; i < addresses.size(); i++) {
-                BigDecimal gas = getCurrentGasPrice(maxGas);
-                log.info("当前gas: {}", gas);
-                BigDecimal currenAmount = getCurrenAmount(amount);
-                log.info("amount: {}", currenAmount);
-                String address = getUnusedAddress(addressMap, addresses);
-                int sleepSeconds = RandomUtil.randomInt(intervalMin, intervalMax);
-                long sleep = sleepSeconds * 60L + RandomUtil.randomInt(1, 30);
+    protected synchronized void prepareTrans(Integer intervalMin, Integer intervalMax, String amount, String maxGas, String executeId, Map<String, Boolean> addressMap, Set<String> set, List<String> addresses) {
+        int i = 0;
+        while (set.size() < addresses.size()) {
+            BigDecimal gas = getCurrentGasPrice(maxGas);
+            BigDecimal currenAmount = getCurrenAmount(amount);
+            String address = getUnusedAddress(addressMap, addresses);
+
+            AmsTradeRecord record = this.getOne(
+                    new LambdaQueryWrapper<AmsTradeRecord>()
+                            .eq(AmsTradeRecord::getExecuteId, executeId)
+                            .eq(AmsTradeRecord::getAddress, address)
+            );
+            if (record != null) {
+                break;
+            }
+            addressMap.put(address, true);
+            set.add(address);
+            int sleepSeconds = RandomUtil.randomInt(intervalMin, intervalMax);
+            long sleep = sleepSeconds * 60L + RandomUtil.randomInt(1, 30);
+            if (i == 0) {
                 log.info("执行器{} ,当前总共有{} 条交易需要执行,当前是第{} 笔交易,第{}笔交易需要等待{} 分钟",
                         executeId,
                         addresses.size(),
                         i + 1,
                         i + 2,
                         sleep / 60);
-                if (i == 0) {
-                    executeTrans(executeId, address, gas, currenAmount);
-                } else {
-                    AmsTradeRecord record = this.getOne(
-                            new LambdaQueryWrapper<AmsTradeRecord>()
-                                    .eq(AmsTradeRecord::getExecuteId, executeId)
-                                    .eq(AmsTradeRecord::getAddress, address)
-                    );
-
-                    if (record == null) {
-                        AMS_SCHEDULER.schedule(() -> {
-                            // todo 调用链上交易
-
-                            //交易入库
-                            executeTrans(executeId, address, gas, currenAmount);
-
-                        }, sleep, TimeUnit.SECONDS);
-                    }
+                log.info("当前gas: {}", gas);
+                log.info("amount: {}", currenAmount);
+                executeTrans(executeId, address, gas, currenAmount);
+                ThreadUtil.safeSleep(sleep);
+                i++;
+            } else {
+                AmsTradeRecord tradeRecord = this.getOne(
+                        new LambdaQueryWrapper<AmsTradeRecord>()
+                                .eq(AmsTradeRecord::getExecuteId, executeId)
+                                .eq(AmsTradeRecord::getAddress, address)
+                );
+
+                if (tradeRecord == null) {
+                    log.info("执行器{} ,当前总共有{} 条交易需要执行,当前是第{} 笔交易,第{}笔交易需要等待{} 分钟",
+                            executeId,
+                            addresses.size(),
+                            i + 1,
+                            i + 2,
+                            sleep / 60);
+                    log.info("当前gas: {}", gas);
+                    log.info("amount: {}", currenAmount);
+                    AMS_SCHEDULER.schedule(() -> {
+                        // todo 调用链上交易
+
+                        //交易入库
+                        executeTrans(executeId, address, gas, currenAmount);
+
+                    }, sleep, TimeUnit.SECONDS);
+                    i++;
                 }
-
-                addressMap.put(address, true);
-                set.add(address);
             }
         }
     }
@@ -139,6 +163,11 @@ public class AmsTradeRecordServiceImpl extends SuperWhaleServiceImpl<AmsTradeRec
         return this.baseMapper.getExportData(userId);
     }
 
+    @Override
+    public List<TradeRecordResponse> listByUserId(String userId) {
+        return this.baseMapper.listByUserId(userId);
+    }
+
     private BigDecimal getCurrenAmount(String amount) {
         return RandomUtil.randomBigDecimal(BigDecimal.ZERO, new BigDecimal(amount));
     }
@@ -179,8 +208,22 @@ public class AmsTradeRecordServiceImpl extends SuperWhaleServiceImpl<AmsTradeRec
     }
 
     private String getRandomAddress(List<String> accountList) {
-        int randomInt = RandomUtil.randomInt(0, accountList.size() - 1);
+        int randomInt = RandomUtil.randomInt(0, accountList.size());
         return accountList.get(randomInt);
     }
 
+
+    @Scheduled(cron = "0/59 * * * * ? ")
+    public void scanTradeStatus() {
+        List<AmsTradeRecord> list = this.list(new LambdaQueryWrapper<AmsTradeRecord>()
+                .eq(AmsTradeRecord::getStatus, 0));
+        for (AmsTradeRecord record : list) {
+            DateTime dateTime = DateUtil.offsetMinute(DateUtil.date(record.getCreateTime()), 1);
+            if (new DateTime().isAfterOrEquals(dateTime)) {
+                record.setStatus(1);
+                this.updateById(record);
+            }
+        }
+    }
+
 }

+ 6 - 1
src/main/resources/application-dev.yml

@@ -9,4 +9,9 @@ spring:
     driver-class-name: com.mysql.cj.jdbc.Driver
     url: jdbc:mysql://122.9.135.98:3306/ams_test?useUnicode=true&characterEncoding=UTF-8
     password: zRJqkCeSDpWUmL5I
-    username: user-swb
+    username: user-swb
+super-whale:
+  redisson:
+    config:
+      address: redis://redis.ichaoj.com:6379
+      password: OpRxb5xB1E8Ejh2v

+ 6 - 1
src/main/resources/application-test.yml

@@ -9,4 +9,9 @@ spring:
     driver-class-name: com.mysql.cj.jdbc.Driver
     url: jdbc:mysql://122.9.135.98:3306/ams_test?useUnicode=true&characterEncoding=UTF-8
     password: zRJqkCeSDpWUmL5I
-    username: user-swb
+    username: user-swb
+super-whale:
+  redisson:
+    config:
+      address: redis://redis.ichaoj.com:6379
+      password: OpRxb5xB1E8Ejh2v

+ 25 - 19
src/main/resources/mapper/AmsAirdropTaskMapper.xml

@@ -13,28 +13,34 @@
                a.estimated_gas,
                b.project_name,
                b.project_logo,
+               b.project_url,
+               er.*,
+               er.max_gas,
                (SELECT COUNT(*)
                 FROM ams_execute_record er
                 WHERE er.flag = 0
-                  and er.task_id = a.ams_task_id
-                  and er.user_id = #{userId}) AS executeTimes,
-
-               (SELECT aer1.execute_status
-                FROM ams_execute_record aer1
-                WHERE aer1.flag = 0
-                  and aer1.task_id = a.ams_task_id
-                  and aer1.user_id = #{userId}
-                ORDER BY aer1.create_time DESC
-                LIMIT 1)                      AS executeStatus,
-               (SELECT aer.create_time
-                FROM ams_execute_record aer
-                WHERE aer.flag = 0
-                  and aer.task_id = a.ams_task_id
-                  and aer.user_id = #{userId}
-                ORDER BY aer.create_time DESC
-                LIMIT 1)                      AS lastExecuteTime
+                  AND er.task_id = a.ams_task_id
+                  AND er.user_id = #{userId}) AS executeTimes
         FROM ams_airdrop_task a
-                 LEFT JOIN ams_airdrop_project b ON a.airdrop_project_id = b.ams_project_id and b.flag = 0
-        where a.flag = 0
+                 LEFT JOIN ams_airdrop_project b ON a.airdrop_project_id = b.ams_project_id
+            AND b.flag = 0
+                 LEFT JOIN (
+            SELECT aer.execute_status,
+                   aer.execute_id,
+                   aer.create_time AS lastExecuteTime,
+                   aer.group_name,
+                   aer.interval_max,
+                   aer.interval_min,
+                   aer.max_gas,
+                   aer.task_id,
+                   aer.project_id
+            FROM ams_execute_record aer
+            WHERE aer.flag = 0
+              AND aer.user_id = #{userId}
+            ORDER BY aer.create_time DESC
+            LIMIT 1
+        ) er ON er.task_id = a.ams_task_id
+            AND er.project_id = b.ams_project_id
+        WHERE a.flag = 0
     </select>
 </mapper>

+ 23 - 2
src/main/resources/mapper/AmsExcuteRecordMapper.xml

@@ -1,5 +1,26 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.ichaoj.ams.mapper.AmsExcuteRecordMapper">
-
+<mapper namespace="com.ichaoj.ams.mapper.AmsExecuteRecordMapper">
+    <select id="pageExecute" resultType="com.ichaoj.ams.response.execute.ExecuteResponse">
+        SELECT count(*) totalCount,
+        er.execute_id, er.execute_times, er.project_id, er.task_id, er.user_id, er.group_name, er.from_asset,
+        er.to_asset, er.interval_min,
+        er.interval_max, er.amount, er.max_gas, er.execute_status, er.create_time, er.update_time,
+        (
+        SELECT sum(r1.gas) from ams_trade_record r1 where r1.flag = 0 and r1.execute_id = er.execute_id
+        ) totalGas,
+        (
+        SELECT sum(r2.amount) from ams_trade_record r2 where r2.flag = 0 and r2.execute_id = er.execute_id
+        ) totalAmount
+        FROM ams_execute_record er
+        WHERE er.flag = 0
+        and er.user_id = #{userId}
+        <if test="request.queryValue != null and request.queryValue != ''">
+            and (
+            er.task_id = #{request.queryValue}
+            or er.execute_id = #{request.queryValue}
+            or er.group_name = #{request.queryValue}
+            )
+        </if>
+    </select>
 </mapper>

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

@@ -25,6 +25,7 @@
             and tr.execute_id = #{request.queryValue}
             or tr.tx_id = #{request.queryValue}
             or tr.address = #{request.queryValue}
+            or er.task_id = #{request.queryValue}
         </if>
         ORDER BY tr.create_time DESC
     </select>
@@ -59,4 +60,13 @@
           and er.user_id = #{userId}
         group by tr.address, task_name, project_name
     </select>
+
+    <select id="listByUserId" resultType="com.ichaoj.ams.response.record.TradeRecordResponse">
+        select *
+        from ams_trade_record tr
+                 inner join ams_execute_record er
+                            on tr.execute_id = er.execute_id and er.user_id = #{userId} and
+                               er.flag = 0
+        where tr.flag = 0
+    </select>
 </mapper>