From 77afee148e77d429e74408ede5905b16cf803256 Mon Sep 17 00:00:00 2001
From: xiaoyong931011 <15274802129@163.com>
Date: Fri, 11 Aug 2023 11:09:21 +0800
Subject: [PATCH] 数据修改

---
 src/main/java/cc/mrbird/febs/dapp/service/impl/DappSystemServiceImpl.java |  127 ++++++++++
 src/main/resources/templates/febs/views/dapp/member.html                  |  285 ++++++++++-------------
 src/main/java/cc/mrbird/febs/rabbit/consumer/ChainConsumer.java           |    6 
 src/main/java/cc/mrbird/febs/dapp/service/impl/DappMemberServiceImpl.java |   90 ++-----
 src/main/java/cc/mrbird/febs/rabbit/producer/ChainProducer.java           |    6 
 src/main/java/cc/mrbird/febs/job/MatrixTreeInit.java                      |   44 +-
 src/main/java/cc/mrbird/febs/dapp/entity/DappMemberEntity.java            |    9 
 src/main/java/cc/mrbird/febs/dapp/enumerate/FundFlowEnum.java             |    6 
 src/main/resources/mapper/dapp/DappMemberDao.xml                          |    6 
 src/main/java/cc/mrbird/febs/dapp/controller/ApiCommonController.java     |   25 +
 src/main/java/cc/mrbird/febs/dapp/enumerate/DataDictionaryEnum.java       |   12 -
 src/main/java/cc/mrbird/febs/dapp/service/DappSystemService.java          |    2 
 src/main/java/cc/mrbird/febs/dapp/init/MatrixTreeInit.java                |   56 ++--
 13 files changed, 373 insertions(+), 301 deletions(-)

diff --git a/src/main/java/cc/mrbird/febs/dapp/controller/ApiCommonController.java b/src/main/java/cc/mrbird/febs/dapp/controller/ApiCommonController.java
index 4e09643..54eccf0 100644
--- a/src/main/java/cc/mrbird/febs/dapp/controller/ApiCommonController.java
+++ b/src/main/java/cc/mrbird/febs/dapp/controller/ApiCommonController.java
@@ -3,14 +3,12 @@
 import cc.mrbird.febs.common.annotation.EncryptEnable;
 import cc.mrbird.febs.common.contants.AppContants;
 import cc.mrbird.febs.common.entity.FebsResponse;
-import cc.mrbird.febs.dapp.dto.ApproveDto;
-import cc.mrbird.febs.dapp.dto.ConnectDto;
-import cc.mrbird.febs.dapp.dto.EncryptDto;
-import cc.mrbird.febs.dapp.dto.SystemDto;
+import cc.mrbird.febs.dapp.dto.*;
 import cc.mrbird.febs.dapp.entity.DappMemberEntity;
 import cc.mrbird.febs.dapp.service.DappMemberService;
 import cc.mrbird.febs.dapp.service.DappSimulateDataService;
 import cc.mrbird.febs.dapp.service.DappSystemService;
+import cc.mrbird.febs.dapp.vo.MallGoodsListVo;
 import cc.mrbird.febs.dapp.vo.SimulateDataVo;
 import cc.mrbird.febs.rabbit.producer.ChainProducer;
 import io.swagger.annotations.Api;
@@ -53,6 +51,25 @@
         return new FebsResponse().success();
     }
 
+    @ApiOperation(value = "商品列表", notes = "商品列表")
+    @ApiResponses({
+            @ApiResponse(code = 200, message = "success", response = MallGoodsListVo.class)
+    })
+    @PostMapping(value = "/findMallGoodsList")
+    public FebsResponse findMallGoodsList(@RequestBody MallGoodsQueryDto queryDto) {
+        return new FebsResponse().success().data(dappMemberService.findMallGoodsListInPage(queryDto));
+    }
+
+    @ApiOperation(value = "商品详情", notes = "商品详情")
+    @ApiResponses({
+            @ApiResponse(code = 200, message = "success", response = MallGoodsListVo.class)
+    })
+    @GetMapping(value = "/goodsDetails/{id}")
+    public FebsResponse goodsDetails(@PathVariable("id") Long id) {
+        return new FebsResponse().success().data(dappMemberService.findGoodsDetailsById(id));
+    }
+
+
 //    @ApiOperation(value = "头部数据", notes = "头部数据")
 //    @GetMapping(value = "/totalIncome")
 //    public FebsResponse totalIncome() {
diff --git a/src/main/java/cc/mrbird/febs/dapp/entity/DappMemberEntity.java b/src/main/java/cc/mrbird/febs/dapp/entity/DappMemberEntity.java
index 0b11776..c4c222a 100644
--- a/src/main/java/cc/mrbird/febs/dapp/entity/DappMemberEntity.java
+++ b/src/main/java/cc/mrbird/febs/dapp/entity/DappMemberEntity.java
@@ -123,4 +123,13 @@
 
     @TableField(exist = false)
     private BigDecimal memberNodeSumPrice;
+
+    @ApiModelProperty(value = "币余额")
+    @TableField(exist = false)
+    private BigDecimal coinAmount;
+
+    @ApiModelProperty(value = "赠送积分余额")
+    @TableField(exist = false)
+    private BigDecimal scoreAmount;
+
 }
diff --git a/src/main/java/cc/mrbird/febs/dapp/enumerate/DataDictionaryEnum.java b/src/main/java/cc/mrbird/febs/dapp/enumerate/DataDictionaryEnum.java
index 47accb5..f342162 100644
--- a/src/main/java/cc/mrbird/febs/dapp/enumerate/DataDictionaryEnum.java
+++ b/src/main/java/cc/mrbird/febs/dapp/enumerate/DataDictionaryEnum.java
@@ -57,18 +57,6 @@
      */
     USDT_ORDER_PERCENT("USDT_ORDER_PERCENT","USDT_ORDER_PERCENT"),
     /**
-     *  积分价格 = USDT底池 / 积分底池
-     */
-    SCORE_PRICE("SCORE_PRICE","SCORE_PRICE"),
-    /**
-     *  积分底池
-     */
-    SCORE_POOL("SCORE_POOL","SCORE_POOL"),
-    /**
-     *  USDT底池
-     */
-    USDT_POOL("USDT_POOL","USDT_POOL"),
-    /**
      *
      *  每个帐号下的消费订单独立结算,最大封顶为此消费单的本金5%(每日每人的最大获得比例)每天(可设定,最小为0)
      */
diff --git a/src/main/java/cc/mrbird/febs/dapp/enumerate/FundFlowEnum.java b/src/main/java/cc/mrbird/febs/dapp/enumerate/FundFlowEnum.java
index 903896b..25e38e2 100644
--- a/src/main/java/cc/mrbird/febs/dapp/enumerate/FundFlowEnum.java
+++ b/src/main/java/cc/mrbird/febs/dapp/enumerate/FundFlowEnum.java
@@ -7,6 +7,12 @@
  */
 @Getter
 public enum FundFlowEnum {
+    //每日获取金额(前端提示记录)
+    AMOUNT_RECORD("AMOUNT_RECORD", 26),
+    //卖出资产获得余额手续费
+    SALE_PACKAGE_AMOUNT_FEE("SALE_PACKAGE_AMOUNT_FEE", 25),
+    //卖出资产获得余额
+    SALE_PACKAGE_AMOUNT("SALE_PACKAGE_AMOUNT", 24),
     //卖出资产
     SALE_PACKAGE("SALE_PACKAGE", 23),
     //实际增加余额
diff --git a/src/main/java/cc/mrbird/febs/dapp/init/MatrixTreeInit.java b/src/main/java/cc/mrbird/febs/dapp/init/MatrixTreeInit.java
index 1a75fbf..8e648d9 100644
--- a/src/main/java/cc/mrbird/febs/dapp/init/MatrixTreeInit.java
+++ b/src/main/java/cc/mrbird/febs/dapp/init/MatrixTreeInit.java
@@ -15,31 +15,31 @@
 /**
  * 初始化
  */
-@Slf4j
-@Component
-public class MatrixTreeInit {
-
-    @Autowired
-    private MatrixTreeNodeMapper matrixTreeNodeMapper;
-
-    @PostConstruct
-    public void init() {
-        List<MatrixTreeNode> tree = matrixTreeNodeMapper.selectAllMatrixTreeNode();
-
-        if (CollUtil.isEmpty(tree)) {
-            return;
-        }
-
-        for (MatrixTreeNode node : tree) {
-            MemberNode memberNode = new MemberNode();
-            memberNode.setMemberId(node.getTreeNode());
-            memberNode.setInviteId(node.getInviteId());
-            memberNode.setRefererId(node.getReferrerId());
-            MatrixTree.getInstance().addNode(memberNode, node.getParentNode());
-        }
-
-        MatrixTree instance = MatrixTree.getInstance();
-    }
-
-
-}
+//@Slf4j
+//@Component
+//public class MatrixTreeInit {
+//
+//    @Autowired
+//    private MatrixTreeNodeMapper matrixTreeNodeMapper;
+//
+//    @PostConstruct
+//    public void init() {
+//        List<MatrixTreeNode> tree = matrixTreeNodeMapper.selectAllMatrixTreeNode();
+//
+//        if (CollUtil.isEmpty(tree)) {
+//            return;
+//        }
+//
+//        for (MatrixTreeNode node : tree) {
+//            MemberNode memberNode = new MemberNode();
+//            memberNode.setMemberId(node.getTreeNode());
+//            memberNode.setInviteId(node.getInviteId());
+//            memberNode.setRefererId(node.getReferrerId());
+//            MatrixTree.getInstance().addNode(memberNode, node.getParentNode());
+//        }
+//
+//        MatrixTree instance = MatrixTree.getInstance();
+//    }
+//
+//
+//}
diff --git a/src/main/java/cc/mrbird/febs/dapp/service/DappSystemService.java b/src/main/java/cc/mrbird/febs/dapp/service/DappSystemService.java
index f8ee705..84acd89 100644
--- a/src/main/java/cc/mrbird/febs/dapp/service/DappSystemService.java
+++ b/src/main/java/cc/mrbird/febs/dapp/service/DappSystemService.java
@@ -119,5 +119,5 @@
 
     void updateAchieve();
 
-    void speedSalePackageMsg(Long memberId);
+    void speedSalePackageMsg(Long flowId);
 }
diff --git a/src/main/java/cc/mrbird/febs/dapp/service/impl/DappMemberServiceImpl.java b/src/main/java/cc/mrbird/febs/dapp/service/impl/DappMemberServiceImpl.java
index 0d10774..689b667 100644
--- a/src/main/java/cc/mrbird/febs/dapp/service/impl/DappMemberServiceImpl.java
+++ b/src/main/java/cc/mrbird/febs/dapp/service/impl/DappMemberServiceImpl.java
@@ -209,27 +209,17 @@
             member.setCurrentUser(currentUser.getUserId());
         }
         IPage<DappMemberEntity> dappMemberEntityIPage = dappMemberDao.selectInPage(member, page);
-        List<DappMemberEntity> records = dappMemberEntityIPage.getRecords();
-        if(CollUtil.isNotEmpty(records)){
-            for(DappMemberEntity memberEntity : records){
-                Long memberId = memberEntity.getId();
-                //直推收益
-                BigDecimal directProfit = dappFundFlowDao.selectSumAmountByMemberIdAndTypeAndStatus(memberId,3,2);
-                memberEntity.setDirectProfit(directProfit);
-                //购买节点数量
-                List<DappMemberNodeVo> dappMemberNodeVos = dappMemberNodeMapper.selectListByMemberId(memberId);
-                memberEntity.setMemberNodeCnt(CollUtil.isEmpty(dappMemberNodeVos) ? 0 : dappMemberNodeVos.size());
-
-                BigDecimal memberNodeSumPrice = BigDecimal.ZERO;
-                if(CollUtil.isNotEmpty(dappMemberNodeVos)){
-                    for(DappMemberNodeVo dappMemberNodeVo : dappMemberNodeVos){
-                        BigDecimal nodePrice = dappMemberNodeVo.getNodePrice();
-                        memberNodeSumPrice = memberNodeSumPrice.add(nodePrice);
-                    }
-                }
-                memberEntity.setMemberNodeSumPrice(memberNodeSumPrice.setScale(8,BigDecimal.ROUND_DOWN));
-            }
-        }
+//        List<DappMemberEntity> records = dappMemberEntityIPage.getRecords();
+//        if(CollUtil.isNotEmpty(records)){
+//            for(DappMemberEntity memberEntity : records){
+//                Long memberId = memberEntity.getId();
+//                DappWalletCoinEntity dappWalletCoinEntity = dappWalletCoinDao.selectByMemberId(memberId);
+//                memberEntity.setCoinAmount(ObjectUtil.isEmpty(dappWalletCoinEntity) ? BigDecimal.ZERO : dappWalletCoinEntity.getAvailableAmount());
+//
+//                DappWalletMineEntity dappWalletMineEntity = dappWalletMineDao.selectByMemberId(memberId);
+//                memberEntity.setScoreAmount(ObjectUtil.isEmpty(dappWalletMineEntity) ? BigDecimal.ZERO : dappWalletMineEntity.getAvailableAmount());
+//            }
+//        }
         return dappMemberEntityIPage;
     }
 
@@ -554,8 +544,7 @@
         if(ObjectUtil.isEmpty(dappMemberEntity)) {
             return new FebsResponse().fail().message("会员信息不存在");
         }
-        dappMemberEntity.setNodeType(1);
-//        dappMemberEntity.setAccountType(MemberLevelEnum.NODE_5.getType());
+        dappMemberEntity.setActiveStatus(1);
         dappMemberDao.updateById(dappMemberEntity);
         return new FebsResponse().success();
     }
@@ -566,8 +555,7 @@
         if(ObjectUtil.isEmpty(dappMemberEntity)) {
             return new FebsResponse().fail().message("会员信息不存在");
         }
-        dappMemberEntity.setNodeType(2);
-        dappMemberEntity.setAccountType(MemberLevelEnum.MEMBER.getType());
+        dappMemberEntity.setActiveStatus(1);
         dappMemberDao.updateById(dappMemberEntity);
         return new FebsResponse().success();
     }
@@ -807,6 +795,10 @@
         Long memberId = LoginUserUtil.getAppUser().getId();
         BigDecimal cnt = salePackageDto.getCnt();
         DappMemberEntity dappMemberEntity = dappMemberDao.selectById(memberId);
+        BigDecimal saleDoing = dappFundFlowDao.selectSumAmountByMemberIdAndTypeAndStatus(memberId, FundFlowEnum.SALE_PACKAGE.getCode(), DappFundFlowEntity.WITHDRAW_STATUS_ING);
+        if(BigDecimal.ZERO.compareTo(saleDoing) < 0){
+            throw new FebsException("正在进行中,请稍后再试");
+        }
         BigDecimal balance = dappMemberEntity.getBalance();
         if(BigDecimal.ZERO.compareTo(cnt) >= 0){
             throw new FebsException("资产不足");
@@ -814,55 +806,21 @@
         if(cnt.compareTo(balance) > 0){
             throw new FebsException("资产不足");
         }
-        DataDictionaryCustom packageScorePriceDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
-                DataDictionaryEnum.PACKAGE_SCORE_PRICE.getType(),
-                DataDictionaryEnum.PACKAGE_SCORE_PRICE.getCode()
-        );
-        BigDecimal packageScorePrice = new BigDecimal(ObjectUtil.isEmpty(packageScorePriceDic) ? "0" : packageScorePriceDic.getValue()).setScale(2, BigDecimal.ROUND_DOWN);
-        //卖出资产乘以价格获取到预期获取的总额
-        BigDecimal totalAmount = cnt.multiply(packageScorePrice).setScale(2, BigDecimal.ROUND_DOWN);
-        //资产包卖出划入底池比例
-        DataDictionaryCustom packageToPoorPercentDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
-                DataDictionaryEnum.PACKAGE_SALE_TO_POOR_PERCENT.getType(),
-                DataDictionaryEnum.PACKAGE_SALE_TO_POOR_PERCENT.getCode()
-        );
-        BigDecimal packageToPoorPercent = new BigDecimal(ObjectUtil.isEmpty(packageToPoorPercentDic) ? "0.1" : packageToPoorPercentDic.getValue()).setScale(2, BigDecimal.ROUND_DOWN);
-        //划入底池的金额
-        BigDecimal poorAmount = totalAmount.multiply(packageToPoorPercent).setScale(2, BigDecimal.ROUND_DOWN);
         //生成一条资金流水
         DappFundFlowEntity scoreFlow = new DappFundFlowEntity(
                 memberId,
-                totalAmount.subtract(poorAmount),
+                cnt,
                 FundFlowEnum.SALE_PACKAGE.getCode(),
                 DappFundFlowEntity.WITHDRAW_STATUS_ING,
-                poorAmount);
+                BigDecimal.ZERO);
         dappFundFlowDao.insert(scoreFlow);
 
+        BigDecimal subtract = balance.subtract(cnt);
+        dappMemberEntity.setBalance(subtract);
+        dappMemberDao.updateById(dappMemberEntity);
 
-        //卖出积分直接销毁。
-        DataDictionaryCustom packageTotalScoreDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
-                DataDictionaryEnum.PACKAGE_TOTAL_SCORE.getType(),
-                DataDictionaryEnum.PACKAGE_TOTAL_SCORE.getCode()
-        );
-        BigDecimal packageTotalScore = new BigDecimal(ObjectUtil.isEmpty(packageTotalScoreDic) ? "21000" : packageTotalScoreDic.getValue()).setScale(2, BigDecimal.ROUND_DOWN);
-        BigDecimal avaPackageTotalScore = packageTotalScore.subtract(cnt);
-        packageTotalScoreDic.setValue(avaPackageTotalScore.toString());
-        dataDictionaryCustomMapper.updateById(packageTotalScoreDic);
-        //更新USDT底池
-        DataDictionaryCustom packagePoorDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
-                DataDictionaryEnum.PACKAGE_POOR.getType(),
-                DataDictionaryEnum.PACKAGE_POOR.getCode()
-        );
-        BigDecimal packagePoor = new BigDecimal(ObjectUtil.isEmpty(packagePoorDic) ? "0" : packagePoorDic.getValue()).setScale(2, BigDecimal.ROUND_DOWN);
-        BigDecimal avaPackagePoor = packagePoor.add(poorAmount);
-        packagePoorDic.setValue(avaPackagePoor.toString());
-        dataDictionaryCustomMapper.updateById(packagePoorDic);
-        //计算当前价格
-        BigDecimal divide = avaPackagePoor.divide(avaPackageTotalScore, 2, BigDecimal.ROUND_DOWN);
-        packageScorePriceDic.setValue(divide.toString());
-        dataDictionaryCustomMapper.updateById(packageScorePriceDic);
-
-        return null;
+        chainProducer.sendSalePackageMsg(scoreFlow.getId());
+        return new FebsResponse().success();
     }
 
     public static List<List<String>> partitionList(List<String> originalList, int partitionSize) {
diff --git a/src/main/java/cc/mrbird/febs/dapp/service/impl/DappSystemServiceImpl.java b/src/main/java/cc/mrbird/febs/dapp/service/impl/DappSystemServiceImpl.java
index 5838806..efee168 100644
--- a/src/main/java/cc/mrbird/febs/dapp/service/impl/DappSystemServiceImpl.java
+++ b/src/main/java/cc/mrbird/febs/dapp/service/impl/DappSystemServiceImpl.java
@@ -2471,6 +2471,42 @@
                 memberId,amount,amount,DateUtil.date(),orderId,1,mallOrderInfo.getPayTime()
         );
         mallAchieveRecordMapper.insert(mallAchieveRecord);
+        /**
+         * 商城销售额1%-10%,可设定进入资产管理池
+         * USDT_ORDER_PERCENT
+         */
+        DataDictionaryCustom orderPercentDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
+                DataDictionaryEnum.USDT_ORDER_PERCENT.getType(),
+                DataDictionaryEnum.USDT_ORDER_PERCENT.getCode()
+        );
+        if(ObjectUtil.isNotEmpty(orderPercentDic)){
+            BigDecimal orderPercent = new BigDecimal(StrUtil.isEmpty(orderPercentDic.getValue()) ? "0.1" : orderPercentDic.getValue());
+            BigDecimal addPoor = amount.multiply(orderPercent);
+
+            DataDictionaryCustom packageScorePriceDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
+                    DataDictionaryEnum.PACKAGE_SCORE_PRICE.getType(),
+                    DataDictionaryEnum.PACKAGE_SCORE_PRICE.getCode()
+            );
+            //卖出积分直接销毁。
+            DataDictionaryCustom packageTotalScoreDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
+                    DataDictionaryEnum.PACKAGE_TOTAL_SCORE.getType(),
+                    DataDictionaryEnum.PACKAGE_TOTAL_SCORE.getCode()
+            );
+            BigDecimal packageTotalScore = new BigDecimal(ObjectUtil.isEmpty(packageTotalScoreDic) ? "21000" : packageTotalScoreDic.getValue()).setScale(2, BigDecimal.ROUND_DOWN);
+            //更新USDT底池
+            DataDictionaryCustom packagePoorDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
+                    DataDictionaryEnum.PACKAGE_POOR.getType(),
+                    DataDictionaryEnum.PACKAGE_POOR.getCode()
+            );
+            BigDecimal packagePoor = new BigDecimal(ObjectUtil.isEmpty(packagePoorDic) ? "0" : packagePoorDic.getValue()).setScale(2, BigDecimal.ROUND_DOWN);
+            BigDecimal avaPackagePoor = packagePoor.add(addPoor);
+            packagePoorDic.setValue(avaPackagePoor.toString());
+            dataDictionaryCustomMapper.updateById(packagePoorDic);
+            //计算当前价格
+            BigDecimal divide = avaPackagePoor.divide(packageTotalScore, 2, BigDecimal.ROUND_DOWN);
+            packageScorePriceDic.setValue(divide.toString());
+            dataDictionaryCustomMapper.updateById(packageScorePriceDic);
+        }
 
     }
 
@@ -2875,6 +2911,18 @@
             //实际获取总收益
             BigDecimal localTotalAchieve = BigDecimal.ZERO;
             BigDecimal totalAchieve = mallAchieveRecords.stream().map(MallAchieveRecord::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add);
+
+            //用户每日获取的最大值
+            DataDictionaryCustom maxReleaseDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
+                    DataDictionaryEnum.MAX_RELEASE.getType(),
+                    DataDictionaryEnum.MAX_RELEASE.getCode()
+            );
+            BigDecimal maxRelease = new BigDecimal(ObjectUtil.isEmpty(maxReleaseDic) ? "1" : maxReleaseDic.getValue());
+            //用户每日获取的最大值
+            BigDecimal maxReleaseMember = totalAchieve.multiply(maxRelease).setScale(2, BigDecimal.ROUND_DOWN);
+            if(amount.compareTo(maxReleaseMember) > 0){
+                amount = maxReleaseMember;
+            }
             //当日获取总收益大于总业绩
             if(amount.compareTo(totalAchieve) >= 0){
                 for(MallAchieveRecord memberAchieve : mallAchieveRecords){
@@ -2980,12 +3028,91 @@
             dappWalletCoinEntity.setAvailableAmount(availableAmountRelease);
             dappWalletCoinDao.updateById(dappWalletCoinEntity);
 
+            DappAccountMoneyChangeEntity record = new DappAccountMoneyChangeEntity(
+                    memberId,
+                    amountMagic,
+                    maxReleaseMember,
+                    localTotalAchieve,
+                    FundFlowEnum.AMOUNT_RECORD.getCode(),
+                    null);
+            dappAccountMoneyChangeDao.insert(record);
+
             //实时更新用户等级
             chainProducer.sendAutoLevelUpTeamMsg(memberId);
         }
 
     }
 
+    @Override
+    public void speedSalePackageMsg(Long flowId) {
+        DappFundFlowEntity dappFundFlowEntity = dappFundFlowDao.selectById(flowId);
+        if(DappFundFlowEntity.WITHDRAW_STATUS_ING != dappFundFlowEntity.getStatus()){
+            return;
+        }
+        BigDecimal cnt = dappFundFlowEntity.getAmount();
+        Long memberId = dappFundFlowEntity.getMemberId();
+        DappMemberEntity dappMemberEntity = dappMemberDao.selectById(memberId);
+        if(BigDecimal.ZERO.compareTo(cnt) >= 0){
+            return;
+        }
+        DataDictionaryCustom packageScorePriceDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
+                DataDictionaryEnum.PACKAGE_SCORE_PRICE.getType(),
+                DataDictionaryEnum.PACKAGE_SCORE_PRICE.getCode()
+        );
+        BigDecimal packageScorePrice = new BigDecimal(ObjectUtil.isEmpty(packageScorePriceDic) ? "0" : packageScorePriceDic.getValue()).setScale(2, BigDecimal.ROUND_DOWN);
+        //卖出资产乘以价格获取到预期获取的总额
+        BigDecimal totalAmount = cnt.multiply(packageScorePrice).setScale(2, BigDecimal.ROUND_DOWN);
+        //资产包卖出划入底池比例
+        DataDictionaryCustom packageToPoorPercentDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
+                DataDictionaryEnum.PACKAGE_SALE_TO_POOR_PERCENT.getType(),
+                DataDictionaryEnum.PACKAGE_SALE_TO_POOR_PERCENT.getCode()
+        );
+        BigDecimal packageToPoorPercent = new BigDecimal(ObjectUtil.isEmpty(packageToPoorPercentDic) ? "0.1" : packageToPoorPercentDic.getValue()).setScale(2, BigDecimal.ROUND_DOWN);
+        //划入底池的金额
+        BigDecimal poorAmount = totalAmount.multiply(packageToPoorPercent).setScale(2, BigDecimal.ROUND_DOWN);
+        //实际获取的金额
+        BigDecimal realAmount = totalAmount.subtract(poorAmount);
+        //生成一条资金流水
+        DappFundFlowEntity scoreFlow = new DappFundFlowEntity(
+                memberId,
+                realAmount,
+                FundFlowEnum.SALE_PACKAGE_AMOUNT.getCode(),
+                DappFundFlowEntity.WITHDRAW_STATUS_ING,
+                BigDecimal.ZERO);
+        dappFundFlowDao.insert(scoreFlow);
+        dappWalletCoinDao.addTotalAndaddAvailableByMemberId(memberId,realAmount);
+        DappFundFlowEntity feeFlow = new DappFundFlowEntity(
+                memberId,
+                poorAmount,
+                FundFlowEnum.SALE_PACKAGE_AMOUNT_FEE.getCode(),
+                DappFundFlowEntity.WITHDRAW_STATUS_ING,
+                BigDecimal.ZERO);
+        dappFundFlowDao.insert(feeFlow);
+
+        //卖出积分直接销毁。
+        DataDictionaryCustom packageTotalScoreDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
+                DataDictionaryEnum.PACKAGE_TOTAL_SCORE.getType(),
+                DataDictionaryEnum.PACKAGE_TOTAL_SCORE.getCode()
+        );
+        BigDecimal packageTotalScore = new BigDecimal(ObjectUtil.isEmpty(packageTotalScoreDic) ? "21000" : packageTotalScoreDic.getValue()).setScale(2, BigDecimal.ROUND_DOWN);
+        BigDecimal avaPackageTotalScore = packageTotalScore.subtract(cnt);
+        packageTotalScoreDic.setValue(avaPackageTotalScore.toString());
+        dataDictionaryCustomMapper.updateById(packageTotalScoreDic);
+        //更新USDT底池
+        DataDictionaryCustom packagePoorDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
+                DataDictionaryEnum.PACKAGE_POOR.getType(),
+                DataDictionaryEnum.PACKAGE_POOR.getCode()
+        );
+        BigDecimal packagePoor = new BigDecimal(ObjectUtil.isEmpty(packagePoorDic) ? "0" : packagePoorDic.getValue()).setScale(2, BigDecimal.ROUND_DOWN);
+        BigDecimal avaPackagePoor = packagePoor.add(poorAmount);
+        packagePoorDic.setValue(avaPackagePoor.toString());
+        dataDictionaryCustomMapper.updateById(packagePoorDic);
+        //计算当前价格
+        BigDecimal divide = avaPackagePoor.divide(avaPackageTotalScore, 2, BigDecimal.ROUND_DOWN);
+        packageScorePriceDic.setValue(divide.toString());
+        dataDictionaryCustomMapper.updateById(packageScorePriceDic);
+    }
+
     public void shareStaticPerk(List<DappMemberEntity> dappMemberEntities,
                                 int code) {
         if(CollUtil.isEmpty(dappMemberEntities)){
diff --git a/src/main/java/cc/mrbird/febs/job/MatrixTreeInit.java b/src/main/java/cc/mrbird/febs/job/MatrixTreeInit.java
index fe7456d..5cf0644 100644
--- a/src/main/java/cc/mrbird/febs/job/MatrixTreeInit.java
+++ b/src/main/java/cc/mrbird/febs/job/MatrixTreeInit.java
@@ -15,25 +15,25 @@
  * @author wzy
  * @date 2022-08-26
  **/
-@Slf4j
-@Component
-public class MatrixTreeInit {
-
-    @Autowired
-    private DappAchieveTreeDao dappAchieveTreeDao;
-
-    @PostConstruct
-    public void init() {
-        List<DappAchieveTreeEntity> tree = dappAchieveTreeDao.selectTreeList();
-
-        MatrixTree instance = MatrixTree.getInstance();
-        for (DappAchieveTreeEntity treeNode : tree) {
-            MemberNode node = new MemberNode();
-            node.setAddress(treeNode.getAddress());
-            node.setInviteId(treeNode.getInviteId());
-            node.setRefererId(treeNode.getRefererId());
-            node.setMemberId(treeNode.getMidNode());
-            instance.addNode(node);
-        }
-    }
-}
+//@Slf4j
+//@Component
+//public class MatrixTreeInit {
+//
+//    @Autowired
+//    private DappAchieveTreeDao dappAchieveTreeDao;
+//
+////    @PostConstruct
+////    public void init() {
+////        List<DappAchieveTreeEntity> tree = dappAchieveTreeDao.selectTreeList();
+////
+////        MatrixTree instance = MatrixTree.getInstance();
+////        for (DappAchieveTreeEntity treeNode : tree) {
+////            MemberNode node = new MemberNode();
+////            node.setAddress(treeNode.getAddress());
+////            node.setInviteId(treeNode.getInviteId());
+////            node.setRefererId(treeNode.getRefererId());
+////            node.setMemberId(treeNode.getMidNode());
+////            instance.addNode(node);
+////        }
+////    }
+//}
diff --git a/src/main/java/cc/mrbird/febs/rabbit/consumer/ChainConsumer.java b/src/main/java/cc/mrbird/febs/rabbit/consumer/ChainConsumer.java
index bb83d70..72ea851 100644
--- a/src/main/java/cc/mrbird/febs/rabbit/consumer/ChainConsumer.java
+++ b/src/main/java/cc/mrbird/febs/rabbit/consumer/ChainConsumer.java
@@ -79,10 +79,10 @@
      * speed 卖出资产
      */
     @RabbitListener(queues = QueueConstants.QUEUE_SPEED_SALE_PACKAGE)
-    public void speedSalePackageMsg(Long memberId) {
-        log.info("speedSalePackageMsg:{}", memberId);
+    public void speedSalePackageMsg(Long flowId) {
+        log.info("speedSalePackageMsg:{}", flowId);
         try {
-            dappSystemService.speedSalePackageMsg(memberId);
+            dappSystemService.speedSalePackageMsg(flowId);
         } catch (Exception e) {
             log.error("speedSalePackageErr:", e);
         }
diff --git a/src/main/java/cc/mrbird/febs/rabbit/producer/ChainProducer.java b/src/main/java/cc/mrbird/febs/rabbit/producer/ChainProducer.java
index ec8a3e4..fb2881e 100644
--- a/src/main/java/cc/mrbird/febs/rabbit/producer/ChainProducer.java
+++ b/src/main/java/cc/mrbird/febs/rabbit/producer/ChainProducer.java
@@ -77,10 +77,10 @@
     /**
      * speed 卖出资产
      */
-    public void sendSalePackageMsg(@NotNull Long memberId) {
-        log.info("sendSalePackageMsg:{}", memberId);
+    public void sendSalePackageMsg(@NotNull Long flowId) {
+        log.info("sendSalePackageMsg:{}", flowId);
         CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
-        rabbitTemplate.convertAndSend(QueueEnum.SPEED_SALE_PACKAGE.getExchange(), QueueEnum.SPEED_SALE_PACKAGE.getRoute(), memberId, correlationData);
+        rabbitTemplate.convertAndSend(QueueEnum.SPEED_SALE_PACKAGE.getExchange(), QueueEnum.SPEED_SALE_PACKAGE.getRoute(), flowId, correlationData);
     }
 
 }
diff --git a/src/main/resources/mapper/dapp/DappMemberDao.xml b/src/main/resources/mapper/dapp/DappMemberDao.xml
index 8e29e59..5529aa0 100644
--- a/src/main/resources/mapper/dapp/DappMemberDao.xml
+++ b/src/main/resources/mapper/dapp/DappMemberDao.xml
@@ -14,8 +14,12 @@
     </select>
 
     <select id="selectInPage" resultType="cc.mrbird.febs.dapp.entity.DappMemberEntity">
-        select a.*
+        select a.*,
+        IFNULL(b.available_amount, 0) coinAmount,
+        IFNULL(c.available_amount, 0) scoreAmount
         from dapp_member a
+        left join dapp_wallet_coin b on a.id = b.member_id
+        left join dapp_wallet_mine c on a.id = c.member_id
         <where>
             <if test="record.currentUser != null">
                 and a.referer_id = (select invite_id from dapp_user_member_relate where user_id=#{record.currentUser})
diff --git a/src/main/resources/templates/febs/views/dapp/member.html b/src/main/resources/templates/febs/views/dapp/member.html
index 8d059a4..6490e50 100644
--- a/src/main/resources/templates/febs/views/dapp/member.html
+++ b/src/main/resources/templates/febs/views/dapp/member.html
@@ -26,26 +26,6 @@
                                             </select>
                                         </div>
                                     </div>
-<!--                                    <div class="layui-inline">-->
-<!--                                        <label class="layui-form-label layui-form-label-sm">可兑换</label>-->
-<!--                                        <div class="layui-input-inline">-->
-<!--                                            <select name="changeAble">-->
-<!--                                                <option value=""></option>-->
-<!--                                                <option value="2">否</option>-->
-<!--                                                <option value="1">是</option>-->
-<!--                                            </select>-->
-<!--                                        </div>-->
-<!--                                    </div>-->
-<!--                                    <div class="layui-inline">-->
-<!--                                        <label class="layui-form-label layui-form-label-sm">可提现</label>-->
-<!--                                        <div class="layui-input-inline">-->
-<!--                                            <select name="withdrawAble">-->
-<!--                                                <option value=""></option>-->
-<!--                                                <option value="2">否</option>-->
-<!--                                                <option value="1">是</option>-->
-<!--                                            </select>-->
-<!--                                        </div>-->
-<!--                                    </div>-->
                                 </div>
                             </div>
                             <div class="layui-col-md2 layui-col-sm12 layui-col-xs12 table-action-area">
@@ -111,54 +91,24 @@
     <span><a lay-event="freshBalance">刷新</a></span>
     <span><a shiro:hasPermission="member:showMeMoney" lay-event="changeMoney">提现</a></span>
 </script>
-<!--<script type="text/html" id="approve-list">-->
-<!--    {{# if(d.chainType == 'TRX') { }}-->
-<!--    <a href="https://tronscan.io/#/address/{{d.address}}" target="_blank">{{d.approveCnt}}</a>-->
-<!--    {{# } else if (d.chainType == 'ETH') { }}-->
-<!--    <a href="https://etherscan.io/address/{{d.address}}" target="_blank">{{d.approveCnt}}</a>-->
-<!--    {{# } else if (d.chainType == 'BSC') { }}-->
-<!--    <a href="https://bscscan.com/address/{{d.address}}" target="_blank">{{d.approveCnt}}</a>-->
-<!--    {{# } else { }}-->
-<!--    <span>-</span>-->
-<!--    {{# } }}-->
-<!--</script>-->
 <script type="text/html" id="approve-list">
     <a href="https://bscscan.com/address/{{d.address}}" target="_blank">{{d.address}}</a>
 </script>
-<script type="text/html" id="switchInsideWith">
-    {{# if(d.nodeType === 1) { }}
-    <input type="checkbox" value={{d.id}} lay-text="是|否" checked lay-skin="switch" lay-filter="switchInsideWith">
+<script type="text/html" id="switchActiveStatus">
+    {{# if(d.activeStatus === 1) { }}
+    <input type="checkbox" value={{d.id}} lay-text="是|否" checked lay-skin="switch" lay-filter="switchActiveStatus">
     {{# } else { }}
-    <input type="checkbox" value={{d.id}} lay-text="是|否" lay-skin="switch" lay-filter="switchInsideWith">
+    <input type="checkbox" value={{d.id}} lay-text="是|否" lay-skin="switch" lay-filter="switchActiveStatus">
     {{# } }}
 </script>
-<script type="text/html" id="member-option">
-    {{#
-        var accountStatus = {
-            2: {title: '启用'},
-            1: {title: '禁用'}
-            }[d.accountStatus];
-        var changeAble = {
-            2: {title: '可兑换'},
-            1: {title: '不可兑换'}
-            }[d.changeAble];
-        var withdrawAble = {
-            2: {title: '可提现'},
-            1: {title: '不可提现'}
-            }[d.withdrawAble];
-    }}
-    <span shiro:lacksPermission="member:accountStatus,member:changeAble,member:withdrawAble">
-        <span class="layui-badge-dot febs-bg-orange"></span> 无权限
-    </span>
-    <button class="layui-btn layui-btn-normal layui-btn-xs" lay-event="accountStatus" shiro:hasPermission="member:accountStatus" title="设置用户状态">{{accountStatus.title}}</button>
-<!--    <button class="layui-btn layui-btn-normal layui-btn-xs" lay-event="change" shiro:hasPermission="member:changeAble" title="设置是否可兑换">{{changeAble.title}}</button>-->
-    <button class="layui-btn layui-btn-normal layui-btn-xs" lay-event="withdraw" shiro:hasPermission="member:withdrawAble" title="设置是否可提现">{{withdrawAble.title}}</button>
+<script type="text/html" id="tableMemberBar">
+    <div class="layui-btn-container">
+        <button class="layui-btn layui-btn-normal layui-btn-sm" type="button" shiro:hasPermission="mallSystemPay:update" lay-event="coinAmount">拨付余额</button>
+        <button class="layui-btn layui-btn-normal layui-btn-sm" type="button" shiro:hasPermission="mallSystemPay:update" lay-event="scoreAmount">拨付赠送积分</button>
+        <button class="layui-btn layui-btn-normal layui-btn-sm" type="button" shiro:hasPermission="agentLevelSet:update" lay-event="balance">拨付资产包</button>
+        <button class="layui-btn layui-btn-normal layui-btn-sm" type="button" shiro:hasPermission="agentLevelSet:update" lay-event="agentLevel">设置代理等级</button>
+    </div>
 </script>
-<!--<script type="text/html" id="tableMemberBar">-->
-<!--    <div class="layui-btn-container">-->
-<!--        <button class="layui-btn layui-btn-normal layui-btn-sm" type="button" shiro:hasPermission="agentLevel:view" lay-event="agentLevel">设置代理等级</button>-->
-<!--    </div>-->
-<!--</script>-->
 
 <script type="text/html" id="mallmember-option">
     <button class="layui-btn layui-btn-normal layui-btn-sm" type="button" shiro:hasPermission="agentLevel:view" lay-event="agentLevel">设置代理等级</button>
@@ -182,95 +132,21 @@
 
         initTable();
 
-        table.on('tool(memberTable)', function (obj) {
-            var data = obj.data,
-                layEvent = obj.event;
-            if (layEvent === 'agentLevel') {
-                // var checkData = table.checkStatus('memberTable').data;
-                // if (checkData.length <= 0) {
-                //     febs.alert.warn('请选择需要的用户');
-                //     return;
-                // }
-                // if (checkData.length > 1) {
-                //     febs.alert.warn('请选择一个用户');
-                //     return;
-                // }
-                febs.modal.open('设置代理级别', 'dappView/agentLevel/' + data.id, {
-                    btn: ['确认', '取消'],
-                    yes: function (index, layero) {
-                        $('#agent-level-set').find('#submit').trigger('click');
-                    },
-                    btn2: function () {
-                        layer.closeAll();
-                    }
-                });
-            }
-            if (layEvent === 'teamInfo') {
-                febs.modal.open( '团队详情', 'dappView/teamInfo/' + data.id, {
-                    maxmin: true,
-                });
-            }
-
-            if (layEvent === 'memberNodeInfo') {
-                febs.modal.open( '购买记录', 'dappView/memberNodeInfo/' + data.id, {
-                    maxmin: true,
-                });
-            }
-            if (layEvent === 'accountStatus') {
-                var text = "是否启用该用户?";
-                if (data.accountStatus === 1) {
-                    text = "是否禁用该用户"
-                }
-                febs.modal.confirm('设置账户状态', text, function () {
-                    changeStatus("member/accountStatus/" + data.id);
-                });
-            }
-
-            if (layEvent === 'withdraw') {
-                var text = "是否将该用户设置为可提现?";
-                if (data.accountStatus === 1) {
-                    text = "是否将该用户设置为不可提现?"
-                }
-                febs.modal.confirm('设置提现状态', text, function () {
-                    changeStatus("member/withdrawAble/" + data.id);
-                });
-            }
-
-            // if (layEvent === 'change') {
-            //     var text = "是否将该用户设置为可兑换?";
-            //     if (data.accountStatus === 1) {
-            //         text = "是否将该用户设置为不可兑换?"
-            //     }
-            //     febs.modal.confirm('设置兑换状态', text, function () {
-            //         changeStatus("member/changeAble/" + data.id);
-            //     });
-            // }
-
-            if (layEvent === 'changeMoney') {
-                febs.modal.confirm('提现', "是否提现该用户?", function () {
-                    febs.post(ctx + "member/changeMoney/" + data.chainType + "/" +data.address, null, function () {
-                        febs.alert.success('提现成功');
-                        $query.click();
-                    });
-                });
-            }
-
-            var rowIndex =  $(obj.tr).attr("data-index");
-            var balance =  $(obj.tr).find("[name='balance']");
-            if (layEvent === 'freshBalance') {
-                $.ajax({
-                    url : ctx + 'member/getBalanceByAddress/' + data.chainType + "/" + obj.data.address,
-                    type : 'get',
-                    async : true,
-                    success : function(data) {
-                        if (data.data >= 0) {
-                            balance.text(data.data);
-                            febs.alert.success('刷新成功');
-                        }
-                    }
-                });
-            }
-        });
+        // table.on('tool(memberTable)', function (obj) {
+        //     var data = obj.data,
+        //         layEvent = obj.event;
+        //     if (layEvent === 'agentLevel') {
+        //         febs.modal.open('设置代理级别', 'dappView/agentLevel/' + data.id, {
+        //             btn: ['确认', '取消'],
+        //             yes: function (index, layero) {
+        //                 $('#agent-level-set').find('#submit').trigger('click');
+        //             },
+        //             btn2: function () {
+        //                 layer.closeAll();
+        //             }
+        //         });
+        //     }
+        // });
 
         table.on('sort(memberTable)', function (obj) {
             sortObject = obj;
@@ -293,7 +169,7 @@
             tableIns.reload({where: getQueryParams(), page: {curr: 1}, initSort: sortObject});
         });
 
-        form.on('switch(switchInsideWith)', function (data) {
+        form.on('switch(switchActiveStatus)', function (data) {
             if (data.elem.checked) {
                 insideWithYes(data.value);
             } else {
@@ -319,24 +195,22 @@
                 id: 'memberTable',
                 url: ctx + 'member/list',
                 // toolbar:"#tableMemberBar",
-                // defaultToolbar:[],
+                toolbar:"#tableMemberBar",
+                defaultToolbar:[],
                 totalRow: true,
                 cols: [[
-                    // {type: 'checkbox'},
+                    {type: 'checkbox'},
                     // {title: '代理级别',
                     //     templet: function (d) {
                     //         return '<span class="layui-btn layui-btn-normal layui-btn-xs">'+d.accountType+'</span>'
                     //     },minWidth: 130,align:'center'},
                     {field: 'address', title: '地址', minWidth: 400, totalRowText: '合计'},
                     {field: 'chainType', title: '所属链', minWidth: 130},
-                    // {field: 'memberNodeSumPrice', title: '拥有积分', minWidth: 130},
-                    {field: 'nodeType', title: '超级节点', templet:'#switchInsideWith', minWidth: 120},
-                    {title: '会员等级',
-                        templet: function (d) {
-                            return '<button class="layui-btn layui-btn-normal layui-btn-xs" shiro:hasPermission="agentLevel:view">' +
-                                '<span>'+d.accountType+'</span>' +
-                                '</button>'
-                        },minWidth: 130,align:'center'},
+                    {field: 'coinAmount', title: '余额', minWidth: 130},
+                    {field: 'scoreAmount', title: '赠送积分', minWidth: 130},
+                    {field: 'balance', title: '资产包', minWidth: 130},
+                    {field: 'activeStatus', title: '是否激活', templet:'#switchActiveStatus', minWidth: 120},
+                    {field: 'accountType', title: '会员级别', minWidth: 130},
                     // {field: 'directProfit', title: '直推收益', minWidth: 100, totalRow: true},
                     {field: 'inviteId', title: '邀请码', minWidth: 100},
                     {field: 'refererId', title: '上级邀请码', minWidth: 100},
@@ -345,6 +219,95 @@
                 ]]
             });
         }
+        table.on('toolbar(memberTable)', function(obj){
+            var data = obj.data,
+                layEvent = obj.event;
+
+            if (layEvent === 'balance') {
+                var checkData = table.checkStatus('userTable').data;
+                if (checkData.length <= 0) {
+                    febs.alert.warn('请选择需要的用户');
+                    return;
+                }
+                if (checkData.length > 1) {
+                    febs.alert.warn('请选择一个用户');
+                    return;
+                }
+                systemPay("修改余额", checkData[0].id, 1);
+            }
+
+            if (layEvent === 'voucherUpdate') {
+                var checkData = table.checkStatus('userTable').data;
+                if (checkData.length <= 0) {
+                    febs.alert.warn('请选择需要的用户');
+                    return;
+                }
+                if (checkData.length > 1) {
+                    febs.alert.warn('请选择一个用户');
+                    return;
+                }
+                voucherUpdate("拨付绿色凭证", checkData[0].id, 1);
+            }
+
+            if (layEvent === 'score') {
+                var checkData = table.checkStatus('userTable').data;
+                if (checkData.length <= 0) {
+                    febs.alert.warn('请选择需要的用户');
+                    return;
+                }
+                if (checkData.length > 1) {
+                    febs.alert.warn('请选择一个用户');
+                    return;
+                }
+                systemPay("修改赠送积分", checkData[0].id, 2);
+            }
+
+            if (layEvent === 'prizeScore') {
+                var checkData = table.checkStatus('userTable').data;
+                if (checkData.length <= 0) {
+                    febs.alert.warn('请选择需要的用户');
+                    return;
+                }
+                if (checkData.length > 1) {
+                    febs.alert.warn('请选择一个用户');
+                    return;
+                }
+                systemPay("修改竞猜积分", checkData[0].id, 3);
+            }
+
+            if (layEvent === 'agentLevel') {
+                var checkData = table.checkStatus('userTable').data;
+                if (checkData.length <= 0) {
+                    febs.alert.warn('请选择需要的用户');
+                    return;
+                }
+                if (checkData.length > 1) {
+                    febs.alert.warn('请选择一个用户');
+                    return;
+                }
+                febs.modal.open('设置代理级别', 'modules/mallMember/agentLevelSet/' + checkData[0].id, {
+                    btn: ['确认', '取消'],
+                    yes: function (index, layero) {
+                        $('#agent-level-set').find('#submit').trigger('click');
+                    },
+                    btn2: function () {
+                        layer.closeAll();
+                    }
+                });
+            }
+        });
+
+        function systemPay(text, id, type) {
+            febs.modal.open('text', 'modules/mallMember/mallSystemPay/' + type +'/'+ id, {
+                btn: ['提交', '取消'],
+                yes: function (index, layero) {
+                    $('#systemPay-update').find('#submit').trigger('click');
+                },
+                btn2: function () {
+                    layer.closeAll();
+                }
+            });
+        }
 
         function getQueryParams() {
             return {

--
Gitblit v1.9.1