KKSU
2024-07-02 7f7a1b01527843ffb178d015a044380acbde4fe2
逻辑
32 files modified
7 files added
5 files deleted
2764 ■■■■■ changed files
src/main/java/cc/mrbird/febs/common/contants/AppContants.java 5 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/chain/ChainEnum.java 13 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/chain/ChainService.java 35 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/chain/ContractEventService.java 6 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/chain/EthUsdtContract.java 33 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/controller/ApiCommonController.java 12 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/controller/ApiDappMemberController.java 95 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/entity/DappMemberEntity.java 11 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/entity/DappStorage.java 22 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/enumerate/DataDictionaryEnum.java 4 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/enumerate/InviteRule.java 40 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/enumerate/MemberLevelEnum.java 40 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/enumerate/MoneyFlowEnum.java 35 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/mapper/DappStorageMapper.java 19 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/service/DappMemberService.java 8 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/service/DappSystemService.java 10 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/service/impl/AdminOperationServiceImpl.java 8 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/service/impl/BscCoinContractEvent.java 125 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/service/impl/BscUsdtContractEvent.java 299 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/service/impl/DappMemberServiceImpl.java 103 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/service/impl/DappSystemServiceImpl.java 392 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/service/impl/DappWalletServiceImpl.java 126 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/vo/TeamDownVo.java 26 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/vo/TeamUpVo.java 35 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/dapp/vo/WalletInfoVo.java 46 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/job/ChainSDMChargeRunner.java 8 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/job/ChainSDMListenerJob.java 101 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/job/ChainSDMRunner.java 59 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/job/MatrixResetJob.java 58 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/job/MatrixTreeInit.java 42 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/job/ProfitDailyJob.java 384 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/rabbit/QueueConstants.java 19 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/rabbit/QueueEnum.java 24 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/rabbit/RabbitConfiguration.java 156 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/rabbit/consumer/ChainConsumer.java 129 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/rabbit/producer/ChainProducer.java 96 ●●●●● patch | view | raw | blame | history
src/main/resources/application-chain.yml 6 ●●●● patch | view | raw | blame | history
src/main/resources/application-charge.yml 62 ●●●●● patch | view | raw | blame | history
src/main/resources/application-dev.yml 8 ●●●● patch | view | raw | blame | history
src/main/resources/application-prod.yml 4 ●●●● patch | view | raw | blame | history
src/main/resources/application.yml 2 ●●● patch | view | raw | blame | history
src/main/resources/mapper/dapp/DappFundFlowDao.xml 1 ●●●● patch | view | raw | blame | history
src/main/resources/mapper/dapp/DappStorageMapper.xml 53 ●●●●● patch | view | raw | blame | history
src/test/java/cc/mrbird/febs/TreeTest.java 4 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/common/contants/AppContants.java
@@ -4,6 +4,11 @@
import java.util.LinkedList;
public class AppContants {
    public static final String DAO_TEAM_PERK_PERCENT = "0.05";
    public static final String DAO_BU_CHANG_PERCENT = "0.02";
    public static final String DAO_JI_LI_PERCENT = "0.06";
    public static final String DAO_NODE_PERCENT = "0.05";
    public static final String DIRECT_PERCENT = "0.08";
    /**
     * 系统用户
src/main/java/cc/mrbird/febs/dapp/chain/ChainEnum.java
@@ -25,10 +25,15 @@
     * 正式 0xb27e44f98543e480dbd071b6605005e3d99b3dd4 https://bsc-dataseed1.ninicoin.io
     *
     */
    BSC_TFC("BSC", "0x0F22E63D2FB18963C57A5Cb3C43403d156D140c2",
            "0x5bd9f75f53693076e19a8f20d66a147bf0a438275463d2b8d85be8ab11780836",
            "https://bsc-dataseed1.ninicoin.io",
            "0x5dc091e47EDcd24709C7922370806d39e6Ad8be9",
//    BSC_TFC("BSC", "0x0F22E63D2FB18963C57A5Cb3C43403d156D140c2",
//            "0x5bd9f75f53693076e19a8f20d66a147bf0a438275463d2b8d85be8ab11780836",
//            "https://bsc-dataseed1.ninicoin.io",
//            "0x5dc091e47EDcd24709C7922370806d39e6Ad8be9",
//            ""),
    BSC_TFC("BSC", "0xCEBfd36e03BD80c7015Cbad17eFfBc33d2923FF3",
            "592cd2f7e57f94cad7eddc6019a9ed8a36ff05cf37037f74cebe1ffacfaabe77",
            "https://data-seed-prebsc-1-s1.bnbchain.org:8545",
            "0x840857BFE8135eab9B4C2E7e140139DEe2E2a479",
            ""),
    /**
src/main/java/cc/mrbird/febs/dapp/chain/ChainService.java
@@ -114,6 +114,41 @@
    }
    public static void receivePeopleEventListener(BigInteger startBlock, BigInteger endBlock, ContractEventService event, String type) {
        ChainEnum chain = ChainEnum.getValueByName(type);
        assert chain != null;
        EthUsdtContract contract = contract(chain.getPrivateKey(), chain.getContractAddress(), chain.getUrl());
        EthFilter filter = getFilter(startBlock, endBlock, chain.getContractAddress());
        Flowable<EthUsdtContract.ReceivePeopleEventResponse> eventFlowable = contract.receivePeopleEventFlowable(filter)
                .doOnError(throwable ->
                        log.error("合约事件监听发生错误: " + throwable.getMessage(), throwable)) // 更具体的错误日志记录
                .retryWhen(errors -> {
                    AtomicInteger counter = new AtomicInteger();
                    return errors.takeWhile(e -> counter.getAndIncrement() != 3)
                            .flatMap(e -> {
                                System.out.println("delay retry by " + counter.get() + " second(s)");
                                return Flowable.timer(counter.get(), TimeUnit.SECONDS);
                            });
                })
                .subscribeOn(Schedulers.io()); // 指定subscribe操作在IO线程中执行,避免阻塞主线程
        eventFlowable.subscribe(
                e -> {
                    try {
                        event.receivePeopleEvent(e); // 处理事件
                    } catch (Exception ex) {
                        // 处理事件时可能出现的异常
                        log.error("处理合约事件时出错", ex);
                    }
                },
                Throwable::printStackTrace, // 打印错误堆栈,或者可以替换为更具体的错误处理逻辑
                () -> log.info("合约事件监听已完成") // 在Flowable完成时执行的逻辑,如记录日志等
        );
    }
    public static void sdmChargeEventListener(BigInteger startBlock, BigInteger endBlock, ContractEventService event, String type) {
        ChainEnum chain = ChainEnum.getValueByName(type);
src/main/java/cc/mrbird/febs/dapp/chain/ContractEventService.java
@@ -14,4 +14,10 @@
     * @param e
     */
    void sdmUSDT(EthUsdtContract.TransferEventResponse e);
    /**
     * 用户存储PEOPLE
     * @param e
     */
    void receivePeopleEvent(EthUsdtContract.ReceivePeopleEventResponse e);
}
src/main/java/cc/mrbird/febs/dapp/chain/EthUsdtContract.java
@@ -127,6 +127,8 @@
    public static final String FUNC_TOUZHU = "touzhu";
    public static final String FUNC_CUNCHU = "received";
    public static final String FUNC_TRANSFER = "transfer";
    public static final String FUNC_TRANSFERFROM = "transferFrom";
@@ -146,6 +148,10 @@
    public static final Event TRANSFER_EVENT = new Event("Transfer",
            Arrays.<TypeReference<?>>asList(new TypeReference<Address>(true) {}, new TypeReference<Address>(true) {}, new TypeReference<Uint256>() {}));
    ;
    public static final Event CUNCHU_EVENT = new Event("received",
            Arrays.<TypeReference<?>>asList(new TypeReference<Address>(true) {}, new TypeReference<Uint256>() {}, new TypeReference<Utf8String>() {}));
    ;
    @Deprecated
@@ -308,6 +314,25 @@
                    typedResponse.tokens = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue();
                }
                return typedResponse;
            }
        });
    }
    public Flowable<ReceivePeopleEventResponse> receivePeopleEventFlowable(EthFilter filter) {
        return web3j.ethLogFlowable(filter).map(new Function<Log, ReceivePeopleEventResponse>() {
            @Override
            public ReceivePeopleEventResponse apply(Log log) {
                EventValuesWithLog eventValues = extractEventParametersWithLog(CUNCHU_EVENT, log);
                ReceivePeopleEventResponse typedResponse = new ReceivePeopleEventResponse();
                if(eventValues!=null){
                    typedResponse.log = log;
                    typedResponse.from = (String) eventValues.getIndexedValues().get(0).getValue();
                    typedResponse.tokens = (BigInteger) eventValues.getNonIndexedValues().get(0).getValue();
                    typedResponse.regFlow = (String) eventValues.getNonIndexedValues().get(1).getValue();
                }
                return typedResponse;
            }
        });
@@ -735,4 +760,12 @@
        public BigInteger tokens;
    }
    public static class ReceivePeopleEventResponse extends BaseEventResponse {
        public String from;
        public BigInteger tokens;
        public String regFlow;
    }
}
src/main/java/cc/mrbird/febs/dapp/controller/ApiCommonController.java
@@ -2,19 +2,12 @@
import cc.mrbird.febs.common.annotation.EncryptEnable;
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.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.SimulateDataVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;
@@ -51,9 +44,4 @@
        return new FebsResponse().success();
    }
//    @ApiOperation(value = "头部数据", notes = "头部数据")
//    @GetMapping(value = "/totalIncome")
//    public FebsResponse totalIncome() {
//        return new FebsResponse().success().data(dappSystemService.findTotalInComeAndList());
//    }
}
src/main/java/cc/mrbird/febs/dapp/controller/ApiDappMemberController.java
@@ -5,14 +5,14 @@
import cc.mrbird.febs.common.entity.FebsResponse;
import cc.mrbird.febs.common.utils.LoginUserUtil;
import cc.mrbird.febs.common.utils.RedisUtils;
import cc.mrbird.febs.dapp.dto.*;
import cc.mrbird.febs.dapp.dto.BuyNodeDto;
import cc.mrbird.febs.dapp.dto.RecordInPageDto;
import cc.mrbird.febs.dapp.dto.WithdrawDto;
import cc.mrbird.febs.dapp.entity.DappMemberEntity;
import cc.mrbird.febs.dapp.service.DappMemberService;
import cc.mrbird.febs.dapp.service.DappSystemService;
import cc.mrbird.febs.dapp.service.DappWalletService;
import cc.mrbird.febs.dapp.vo.MemberNodeVo;
import cc.mrbird.febs.dapp.vo.NodeTypeVo;
import cc.mrbird.febs.dapp.vo.TeamListVo;
import cc.mrbird.febs.dapp.vo.TeamDownVo;
import cc.mrbird.febs.dapp.vo.TeamUpVo;
import cc.mrbird.febs.dapp.vo.WalletInfoVo;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@@ -38,7 +38,6 @@
public class ApiDappMemberController {
    private final DappWalletService dappWalletService;
    private final DappSystemService dappSystemService;
    private final DappMemberService dappMemberService;
    private final RedisUtils redisUtils;
@@ -52,58 +51,34 @@
        return new FebsResponse().success().data(walletInfoVo);
    }
    @ApiOperation(value = "购买节点", notes = "购买节点")
    @PostMapping(value = "/buyNode")
    public FebsResponse buyNode(@RequestBody BuyNodeDto buyNodeDto) {
        return new FebsResponse().success().data(dappWalletService.buyNode(buyNodeDto));
    }
    @ApiOperation(value = "获取星团集合", notes = "获取星团集合")
    @ApiResponses({
            @ApiResponse(code = 200, message = "success", response = NodeTypeVo.class)
    })
    @PostMapping(value = "/nodeList")
    public FebsResponse nodeList() {
        return dappWalletService.nodeList();
    }
    @ApiOperation(value = "购买星团", notes = "购买星团")
    @PostMapping(value = "/buyStar")
    public FebsResponse buyStar(@RequestBody BuyStarDto buyStarDto) {
        return new FebsResponse().success().data(dappWalletService.buyStar(buyStarDto));
    }
    @ApiOperation(value = "星团矩阵", notes = "星团矩阵")
    @ApiResponses({
            @ApiResponse(code = 200, message = "success", response = MemberNodeVo.class)
    })
    @PostMapping(value = "/memberNode")
    public FebsResponse memberNode(@RequestBody MemberNodeDto memberNodeDto) {
        return new FebsResponse().success().data(dappWalletService.memberNode(memberNodeDto));
    }
    @ApiOperation(value = "转账", notes = "转账")
    @PostMapping(value = "/transfer")
    public FebsResponse transfer(@RequestBody TransferDto transferDto) {
        return new FebsResponse().success().data(dappWalletService.transfer(transferDto));
    }
    @ApiOperation(value = "手续费充值", notes = "手续费充值")
    @PostMapping(value = "/chargeFee")
    public FebsResponse chargeFee(@RequestBody ChargeFeeDto chargeFeeDto) {
        return new FebsResponse().success().data(dappWalletService.chargeFee(chargeFeeDto));
    }
    @ApiOperation(value = "手续费计算", notes = "手续费计算")
    @PostMapping(value = "/calPrice")
    public FebsResponse calPrice(@RequestBody PriceDto priceDto) {
        return new FebsResponse().success().data(dappWalletService.calPrice(priceDto));
    }
    @ApiOperation(value = "记录列表", notes = "记录列表")
    @ApiOperation(value = "资金流水", notes = "资金流水")
    @PostMapping(value = "/recordInPage")
    public FebsResponse recordInPage(@RequestBody RecordInPageDto recordInPageDto) {
        return new FebsResponse().success().data(dappWalletService.recordInPage(recordInPageDto));
    }
    @ApiOperation(value = "我的团队-上半部分", notes = "我的团队-上半部分")
    @ApiResponses({
            @ApiResponse(code = 200, message = "success", response = TeamUpVo.class)
    })
    @PostMapping(value = "/teamUp")
    public FebsResponse teamUp() {
        return new FebsResponse().success().data(dappMemberService.teamUp());
    }
    @ApiOperation(value = "我的团队-列表", notes = "我的团队-列表")
    @ApiResponses({
            @ApiResponse(code = 200, message = "success", response = TeamDownVo.class)
    })
    @PostMapping(value = "/teamDown")
    public FebsResponse teamDown() {
        return new FebsResponse().success().data(dappMemberService.teamDown());
    }
    @ApiOperation(value = "存储", notes = "存储")
    @PostMapping(value = "/buyNode")
    public FebsResponse buyNode(@RequestBody BuyNodeDto buyNodeDto) {
        return new FebsResponse().success().data(dappWalletService.buyNode(buyNodeDto));
    }
    @ApiOperation(value = "提现", notes = "提现")
@@ -113,15 +88,7 @@
        return new FebsResponse().success().message("success");
    }
    @ApiOperation(value = "我的团队", notes = "我的团队")
    @ApiResponses({
            @ApiResponse(code = 200, message = "success", response = TeamListVo.class)
    })
    @PostMapping(value = "/team")
    public FebsResponse team() {
        return new FebsResponse().success().data(dappMemberService.findTeamList());
    }
    @ApiOperation(value = "退出", notes = "退出")
    @PostMapping(value = "/logout")
    public FebsResponse logout() {
        DappMemberEntity member = LoginUserUtil.getAppUser();
src/main/java/cc/mrbird/febs/dapp/entity/DappMemberEntity.java
@@ -58,13 +58,22 @@
     * 账号类型 admin normal
     */
    private String accountType;
    //出局总额度
    /**
     * 存储people的时候增加
     * 受到任何收益的时候减少
     * 小于等于0时,用户的激活状态【activeStatus】改成未激活,得不到任何奖励
     */
    private BigDecimal usdtBalance;
    /**
     * 激活状态 1-已激活 2-未激活
     */
    private Integer activeStatus;
    /**
     * 会员层级
     */
    private Integer level;
    //是否购买节点 0 - 否  1 - 是
    private Integer buyNode;
src/main/java/cc/mrbird/febs/dapp/entity/DappStorage.java
New file
@@ -0,0 +1,22 @@
package cc.mrbird.febs.dapp.entity;
import cc.mrbird.febs.common.entity.BaseEntity;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.math.BigDecimal;
@Data
@TableName("dapp_storage")
public class DappStorage  extends BaseEntity {
    private Long memberId;
    private Integer state;//1-释放中 2-已结束
    private BigDecimal amount;
    private BigDecimal releasePercent;
    private BigDecimal releaseAmount;
}
src/main/java/cc/mrbird/febs/dapp/enumerate/DataDictionaryEnum.java
@@ -4,6 +4,10 @@
@Getter
public enum DataDictionaryEnum {
    WITHDRAW_PERCENT("WITHDRAW_PERCENT","WITHDRAW_PERCENT"),
    RELEASE_PERCENT("RELEASE_PERCENT","RELEASE_PERCENT"),
    JILI_CHI("JILI_CHI","JILI_CHI"),
    BUCAHNG_CHI("BUCAHNG_CHI","BUCAHNG_CHI"),
    //每日节点购买最大值
    BUY_NODE_NUM("BUY_NODE_NUM","BUY_NODE_NUM"),
    //提现手续费率
src/main/java/cc/mrbird/febs/dapp/enumerate/InviteRule.java
@@ -7,16 +7,36 @@
    /**
     *  层级 直推人数 奖励百分比
     */
    LEVEL_10(10,3,1),
    LEVEL_9(9,3,1),
    LEVEL_8(8,3,1),
    LEVEL_7(7,3,1),
    LEVEL_6(6,3,1),
    LEVEL_5(5,3,1),
    LEVEL_4(4,3,1),
    LEVEL_3(3,2,1),
    LEVEL_2(2,2,1),
    LEVEL_1(1,2,1);
    LEVEL_30(30,15,7),
    LEVEL_29(29,15,7),
    LEVEL_28(28,14,7),
    LEVEL_27(27,14,7),
    LEVEL_26(26,13,7),
    LEVEL_25(25,13,4),
    LEVEL_24(24,12,4),
    LEVEL_23(23,12,4),
    LEVEL_22(22,11,4),
    LEVEL_21(21,11,4),
    LEVEL_20(20,10,4),
    LEVEL_19(19,10,4),
    LEVEL_18(18,9,4),
    LEVEL_17(17,9,4),
    LEVEL_16(16,8,4),
    LEVEL_15(15,8,5),
    LEVEL_14(14,7,5),
    LEVEL_13(13,7,5),
    LEVEL_12(12,6,5),
    LEVEL_11(11,6,5),
    LEVEL_10(10,5,6),
    LEVEL_9(9,5,6),
    LEVEL_8(8,4,6),
    LEVEL_7(7,4,6),
    LEVEL_6(6,3,6),
    LEVEL_5(5,3,7),
    LEVEL_4(4,2,7),
    LEVEL_3(3,2,7),
    LEVEL_2(2,1,7),
    LEVEL_1(1,1,7);
    private int level;
    private int InviteNum;
src/main/java/cc/mrbird/febs/dapp/enumerate/MemberLevelEnum.java
New file
@@ -0,0 +1,40 @@
package cc.mrbird.febs.dapp.enumerate;
import lombok.Getter;
@Getter
public enum MemberLevelEnum {
    DAO_3("DAO_3",3,5000000,2),
    DAO_2("DAO_2",2,1000000,2),
    DAO_1("DAO_1",1,300000,2),
    DAO_0("DAO_0",0,0,2);
    private String type;
    private Integer code;
    private Integer levelAchieve;//业绩需求
    private Integer directNum;//直推需求
    MemberLevelEnum(String type, Integer code,Integer levelAchieve,Integer directNum) {
        this.type = type;
        this.code = code;
        this.levelAchieve = levelAchieve;
        this.directNum = directNum;
    }
    public String getLevelType(Integer code){
        String type = null;
        for (MemberLevelEnum value : MemberLevelEnum.values()) {
            if(value.code.equals(code)){
                type = value.type;
            }
        }
        return type;
    }
}
src/main/java/cc/mrbird/febs/dapp/enumerate/MoneyFlowEnum.java
New file
@@ -0,0 +1,35 @@
package cc.mrbird.febs.dapp.enumerate;
import lombok.Getter;
/**
 *
 * 1-静态收益 2-直推奖 3-代理收益 4-排名收益 5-总监收益 6-社区点补 7-一代收益 8-提现 9-转增 10-支付 11-退款
 * @author wzy
 * @date 2021-09-24
 **/
@Getter
public enum MoneyFlowEnum {
    STATIC_PERK(11,"静态释放:{}"),
    TEAM_THREE_PERK(10,"DAO3团队激励:激励:{}"),
    TEAM_TWO_PERK(9,"DAO2团队激励:激励:{}"),
    TEAM_ONE_PERK(8,"DAO1团队激励:激励:{}"),
    ZHI_TUI_JI_LI_PERK(7,"直推激励:业绩:{},排名:{},激励:{}"),
    DA_DAN_JI_LI_PERK(6,"大单激励:{}。激励:{}"),
    BU_CHANG_PERK(5,"补偿池:{}。补偿:{}"),
    NODE_PERK(4,"存储:{}。人数:{},节点奖励:{}"),
    DIRECT_PERK(3,"存储:{}。直推奖励:{}"),
    DYNAMIC_PERK(2,"存储:{}。动态奖励,直推:{},层级:{}"),
    CUN_CHU(1,"存储PEOPLE:{}")
    ;
    private int value;
    private String descrition;
    MoneyFlowEnum(int value, String descrition) {
        this.value = value;
        this.descrition = descrition;
    }
}
src/main/java/cc/mrbird/febs/dapp/mapper/DappStorageMapper.java
New file
@@ -0,0 +1,19 @@
package cc.mrbird.febs.dapp.mapper;
import cc.mrbird.febs.dapp.entity.DappStorage;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import java.util.Date;
import java.util.List;
public interface DappStorageMapper extends BaseMapper<DappStorage> {
    DappStorage selectOneByDateDesc( @Param("date") Date date);
    List<DappStorage> selectListByDateDesc( @Param("date") Date date);
    List<DappStorage> selectListByDate( @Param("date") Date date);
    DappStorage selectAmountByDesc(@Param("date") Date date,int offset,int count);
}
src/main/java/cc/mrbird/febs/dapp/service/DappMemberService.java
@@ -8,9 +8,13 @@
import cc.mrbird.febs.dapp.entity.DappTransferRecordEntity;
import cc.mrbird.febs.dapp.entity.DbMemberNode;
import cc.mrbird.febs.dapp.vo.AdminSystemFeeVo;
import cc.mrbird.febs.dapp.vo.TeamDownVo;
import cc.mrbird.febs.dapp.vo.TeamListVo;
import cc.mrbird.febs.dapp.vo.TeamUpVo;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
public interface DappMemberService extends IService<DappMemberEntity> {
@@ -45,4 +49,8 @@
    void setSystemFee(AdminSystemFeeVo adminSystemFeeVo);
    IPage<DbMemberNode> memberNodeList(DbMemberNode dbMemberNode, QueryRequest request);
    TeamUpVo teamUp();
    List<TeamDownVo> teamDown();
}
src/main/java/cc/mrbird/febs/dapp/service/DappSystemService.java
@@ -3,6 +3,8 @@
import cc.mrbird.febs.dapp.dto.SystemDto;
import cc.mrbird.febs.dapp.entity.DbMemberNode;
import java.math.BigDecimal;
public interface DappSystemService {
    SystemDto system();
@@ -29,4 +31,12 @@
    void invitePerkMsg(Long id);
    void nodePerkMsg(Long id);
    void directPerkMsg(Long id);
    void updateBalanceInsertFlow(BigDecimal daoNodeAmount, Long memberId, Integer type, String description);
    void teamPerk(Long id);
    void MemberLevel(Long id);
}
src/main/java/cc/mrbird/febs/dapp/service/impl/AdminOperationServiceImpl.java
@@ -3,7 +3,9 @@
import cc.mrbird.febs.common.entity.FebsResponse;
import cc.mrbird.febs.common.entity.QueryRequest;
import cc.mrbird.febs.common.exception.FebsException;
import cc.mrbird.febs.dapp.entity.*;
import cc.mrbird.febs.dapp.entity.DappFundFlowEntity;
import cc.mrbird.febs.dapp.entity.DappMemberEntity;
import cc.mrbird.febs.dapp.entity.MemberCoinWithdrawEntity;
import cc.mrbird.febs.dapp.mapper.*;
import cc.mrbird.febs.dapp.service.AdminOperationService;
import cc.mrbird.febs.dapp.service.DappWalletService;
@@ -16,8 +18,6 @@
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
@Service
@RequiredArgsConstructor
@@ -56,7 +56,7 @@
        dappFundFlowEntity.setStatus(DappFundFlowEntity.WITHDRAW_STATUS_AGREE);
        dappFundFlowDao.updateById(dappFundFlowEntity);
        chainProducer.sendFeeDistributeMsg(dappFundFlowEntity.getId());
//        chainProducer.sendFeeDistributeMsg(dappFundFlowEntity.getId());
        return new FebsResponse().success();
    }
src/main/java/cc/mrbird/febs/dapp/service/impl/BscCoinContractEvent.java
@@ -1,15 +1,17 @@
package cc.mrbird.febs.dapp.service.impl;
import cc.mrbird.febs.common.utils.RedisUtils;
import cc.mrbird.febs.dapp.chain.ChainEnum;
import cc.mrbird.febs.dapp.chain.ChainService;
import cc.mrbird.febs.dapp.chain.ContractEventService;
import cc.mrbird.febs.dapp.chain.EthUsdtContract;
import cc.mrbird.febs.dapp.entity.DappFundFlowEntity;
import cc.mrbird.febs.dapp.entity.DappMemberEntity;
import cc.mrbird.febs.dapp.entity.DappStorage;
import cc.mrbird.febs.dapp.entity.DataDictionaryCustom;
import cc.mrbird.febs.dapp.enumerate.DataDictionaryEnum;
import cc.mrbird.febs.dapp.mapper.DappFundFlowDao;
import cc.mrbird.febs.dapp.mapper.DappStorageMapper;
import cc.mrbird.febs.dapp.mapper.DataDictionaryCustomMapper;
import cc.mrbird.febs.dapp.service.DappMemberService;
import cc.mrbird.febs.dapp.service.DappWalletService;
import cc.mrbird.febs.rabbit.producer.ChainProducer;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -26,15 +28,14 @@
    @Resource
    private DappMemberService dappMemberService;
    @Resource
    private DappFundFlowDao dappFundFlowDao;
    @Resource
    private RedisUtils redisUtils;
    private DataDictionaryCustomMapper dataDictionaryCustomMapper;
    @Resource
    private DappWalletService dappWalletService;
    private DappStorageMapper dappStorageMapper;
    @Resource
    private ChainProducer chainProducer;
    public static void main(String[] args) {
        System.out.println(Numeric.toBigInt("0x12e4e85"));
@@ -43,39 +44,89 @@
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void compile(EthUsdtContract.TransferEventResponse e) {
        if (e.to == null) {
            return;
        }
        if ("0x0Ba249b2FAC0061dd9c388Bd607418E16490A3fd".toLowerCase().equals(e.to)) {
            log.info("触发GE手续费监听");
            int decimals = ChainService.getInstance(ChainEnum.BSC_TFC.name()).decimals();
            // 账户是否已经注册
            DappMemberEntity fromMember = dappMemberService.findByAddress(e.from, null);
            if (fromMember == null) {
                return;
            }
            BigInteger tokens = e.tokens;
            BigDecimal amount = new BigDecimal(tokens.toString()).divide(BigDecimal.TEN.pow(decimals), decimals, RoundingMode.HALF_DOWN);
            // 充值手续费
            DappFundFlowEntity fundFlow = dappFundFlowDao.selectByFromHash(e.log.getTransactionHash(), null);
            if (fundFlow != null && fundFlow.getStatus() != 1) {
                return;
            }
            // 更改状态为已同步
            fundFlow.setStatus(2);
            dappFundFlowDao.updateById(fundFlow);
            dappWalletService.updateWalletMineWithLock(amount, fromMember.getId(), 1);
        }
    }
    @Override
    public void sdmUSDT(EthUsdtContract.TransferEventResponse e) {
        return;
    }
    @Override
    public void receivePeopleEvent(EthUsdtContract.ReceivePeopleEventResponse e) {
        if (e.from == null) {
            return;
        }
        if (e.regFlow == null) {
            return;
        }
        Long flowId = Long.parseLong(e.regFlow);
//        int decimals = ChainService.getInstance(ChainEnum.BSC_TFC.name()).decimals();
        int decimals = 18;
        BigInteger tokens = e.tokens;
        BigDecimal amount = new BigDecimal(tokens.toString()).divide(BigDecimal.TEN.pow(decimals), decimals, RoundingMode.HALF_DOWN);
        log.info("触发用户存储:{},金额:{},流水ID:{}",e.from,amount,flowId);
        // 账户是否已经注册
        DappMemberEntity fromMember = dappMemberService.findByAddress(e.from, null);
        if (fromMember == null) {
            return;
        }
        // 判断是否已经同步过了
        DappFundFlowEntity fundFlow = dappFundFlowDao.selectById(flowId);
        if (fundFlow != null && fundFlow.getStatus() != 1) {
            return;
        }
        // 更改状态为已同步
        fundFlow.setStatus(2);
        dappFundFlowDao.updateById(fundFlow);
        log.info("触发用户存储:{},金额:{},流水ID:{}",e.from,amount,flowId);
        /**
         * 新增一条记录
         */
        DataDictionaryCustom dataDictionaryCustom = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
                DataDictionaryEnum.RELEASE_PERCENT.getType(),
                DataDictionaryEnum.RELEASE_PERCENT.getCode()
        );
        BigDecimal releasePercent = new BigDecimal(dataDictionaryCustom.getValue());
        DappStorage dappStorage = new DappStorage();
        dappStorage.setState(1);
        dappStorage.setAmount(amount);
        dappStorage.setReleasePercent(releasePercent);
        BigDecimal releaseAmount = amount.multiply(releasePercent).setScale(2, BigDecimal.ROUND_DOWN);
        dappStorage.setReleaseAmount(releaseAmount);
        dappStorageMapper.insert(dappStorage);
        Long id = fundFlow.getId();
        Long memberId = fromMember.getId();
        /**
         * 发送直推8%
         */
        chainProducer.sendDirectPerkMsg(id);
        /**
         * DAO成员动态:
         *      * 1.直推1个拿2代,直推10个拿20代,直推15个拿30代,最高30代
         */
        chainProducer.sendMemberDynamicPerkMsg(id);
        /**
         *
         *      * 六、永动补偿池2%
         *      * 五、DAO永动激励池:6%
         *      * 四、DAO联盟委员会 :   5%  (50名全球DAO委员)
         */
        chainProducer.sendNodePerkMsg(id);
        /**
         *3.  成员升级
         *      *       DAO1:小区业绩30万/币  加权分红50%
         *      *       DAO2:小区业绩100万/币 加权分红30%
         *      *       DAO3:小区业绩500万/币加权分红20%
         */
        chainProducer.sendMemberLevel(memberId);
    }
}
src/main/java/cc/mrbird/febs/dapp/service/impl/BscUsdtContractEvent.java
@@ -1,22 +1,19 @@
package cc.mrbird.febs.dapp.service.impl;
import cc.mrbird.febs.common.utils.RedisUtils;
import cc.mrbird.febs.dapp.chain.*;
import cc.mrbird.febs.dapp.chain.ChainEnum;
import cc.mrbird.febs.dapp.chain.ChainService;
import cc.mrbird.febs.dapp.chain.ContractEventService;
import cc.mrbird.febs.dapp.chain.EthUsdtContract;
import cc.mrbird.febs.dapp.entity.DappFundFlowEntity;
import cc.mrbird.febs.dapp.entity.DappMemberEntity;
import cc.mrbird.febs.dapp.entity.DappTransferRecordEntity;
import cc.mrbird.febs.dapp.entity.DappStorage;
import cc.mrbird.febs.dapp.entity.DataDictionaryCustom;
import cc.mrbird.febs.dapp.enumerate.DataDictionaryEnum;
import cc.mrbird.febs.dapp.mapper.DappFundFlowDao;
import cc.mrbird.febs.dapp.mapper.DappMemberDao;
import cc.mrbird.febs.dapp.mapper.DappWalletCoinDao;
import cc.mrbird.febs.dapp.mapper.DappStorageMapper;
import cc.mrbird.febs.dapp.mapper.DataDictionaryCustomMapper;
import cc.mrbird.febs.dapp.service.DappWalletService;
import cc.mrbird.febs.dapp.utils.OnlineTransferUtil;
import cc.mrbird.febs.dapp.service.DappMemberService;
import cc.mrbird.febs.rabbit.producer.ChainProducer;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@@ -24,273 +21,105 @@
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
import java.util.List;
@Slf4j
@Service
public class BscUsdtContractEvent implements ContractEventService {
    @Resource
    private RedisUtils redisUtils;
    private DappMemberService dappMemberService;
    @Resource
    private DappFundFlowDao dappFundFlowDao;
    @Resource
    private DappMemberDao dappMemberDao;
    @Resource
    private DataDictionaryCustomMapper dataDictionaryCustomMapper;
    @Resource
    private DappWalletService dappWalletService;
    @Resource
    private DappWalletCoinDao dappWalletCoinDao;
    private DappStorageMapper dappStorageMapper;
    @Resource
    private ChainProducer chainProducer;
    @Override
    public void compile(EthUsdtContract.TransferEventResponse e) {
        return;
//        if (e.to == null) {
//            return;
//        }
//
//        redisUtils.set(AppContants.REDIS_KEY_BLOCK_USDT_NUM, e.log.getBlockNumber());
//        // 判断对方打款地址是否为源池地址
//        if (ChainEnum.BSC_USDT.getAddress().toLowerCase().equals(e.to)) {
//
//            redisUtils.set(AppContants.REDIS_KEY_BLOCK_ETH_INCREMENT_NUM, e.log.getBlockNumber());
//
//            // 如果得到触发,则休眠10秒。 因为此处监听器触发可能优先于前端调用transfer接口
////            try {
////                Thread.sleep(10000);
////            } catch (InterruptedException ex) {
////                ex.printStackTrace();
////            }
//
//            ContractChainService sourceUsdtInstance = ChainService.getInstance(ChainEnum.BSC_USDT.name());
//            int decimals = sourceUsdtInstance.decimals();
//            if (e.from.equals("0xaa25aa7a19f9c426e07dee59b12f944f4d9f1dd3")) {
//                return;
//            }
//
//            BigInteger tokens = e.tokens;
//            BigDecimal amount = new BigDecimal(tokens.toString()).divide(BigDecimal.TEN.pow(decimals), decimals, RoundingMode.HALF_DOWN);
//
//            DappFundFlowEntity fundFlow = dappFundFlowDao.selectByFromHash(e.log.getTransactionHash(), null);
//            if(ObjectUtil.isNotEmpty(fundFlow) && 1 == fundFlow.getStatus()){
//                log.info("触发USDT合约监听事件-买入贡献值,金额:{}",amount);
//                if(1 == fundFlow.getType()){//认购贡献值 1
//                    if (fundFlow == null) {
//                        List<DappFundFlowEntity> flows = dappFundFlowDao.selectFundFlowListByAddress(e.from, 1);
//                        if (CollUtil.isEmpty(flows)) {
//                            OnlineTransferUtil.addTransferRecord(e.from, e.to, amount, e.log.getTransactionHash(), DappTransferRecordEntity.TRANSFER_SOURCE_FLAG_ONLINE, "USDT");
//                            log.info("本地无交易:{}", e.log.getTransactionHash());
//                            return;
//                        }
//
//                        for (DappFundFlowEntity flow : flows) {
//                            if (flow.getStatus() == 1) {
//                                if (amount.compareTo(flow.getAmount().multiply(flow.getNewestPrice()).setScale(4, RoundingMode.HALF_UP)) == 0) {
//                                    fundFlow = flow;
//                                    fundFlow.setFromHash(e.log.getTransactionHash());
//                                    break;
//                                }
//                            }
//                        }
//                    }
//
//                    if (fundFlow == null) {
//                        return;
//                    }
//
//                    fundFlow.setAmount(fundFlow.getAmount().negate());
//                    // 更改状态为已同步
//                    fundFlow.setStatus(2);
//                    dappFundFlowDao.updateById(fundFlow);
//                    //生成业绩数
//                    chainProducer.sendAchieveTreeMsg(fundFlow.getMemberId());
//                    //分发手续费给节点
//                    buyNodePerk(amount);
//
//                }else if(13 == fundFlow.getType()){//认购节点 13
//
//                    log.info("触发USDT合约监听事件-认购节点,金额:{}",amount);
//                    fundFlow.setAmount(fundFlow.getAmount().negate());
//                    // 更改状态为已同步
//                    fundFlow.setStatus(2);
//                    dappFundFlowDao.updateById(fundFlow);
//
//                    Long memberId = fundFlow.getMemberId();
//                    DappMemberEntity dappMemberEntity = dappMemberDao.selectById(memberId);
//                    dappMemberEntity.setBuyNode(1);
//                    dappMemberDao.updateById(dappMemberEntity);
//                }
//            }else{
//                return;
//            }
//        }
    }
    @Override
    public void sdmUSDT(EthUsdtContract.TransferEventResponse e) {
        if (e.to == null) {
            return;
        }
//        redisUtils.set(AppContants.REDIS_KEY_BLOCK_USDT_NUM, e.log.getBlockNumber());
        // 判断对方打款地址是否为源池地址
        if ("0x0Ba249b2FAC0061dd9c388Bd607418E16490A3fd".toLowerCase().equals(e.to)) {
//            redisUtils.set(AppContants.REDIS_KEY_BLOCK_ETH_INCREMENT_NUM, e.log.getBlockNumber());
            // 如果得到触发,则休眠10秒。 因为此处监听器触发可能优先于前端调用transfer接口
//            try {
//                Thread.sleep(10000);
//            } catch (InterruptedException ex) {
//                ex.printStackTrace();
//            }
            ContractChainService sourceUsdtInstance = ChainService.getInstance(ChainEnum.BSC_USDT.name());
            int decimals = sourceUsdtInstance.decimals();
            if (e.from.equals("0x0Ba249b2FAC0061dd9c388Bd607418E16490A3fd")) {
                return;
            }
            String fromAddress = e.from;
            DappMemberEntity fromMember = dappMemberDao.selectByAddress(fromAddress, null);
            if(ObjectUtil.isEmpty(fromMember)){
    @Override
    public void receivePeopleEvent(EthUsdtContract.ReceivePeopleEventResponse e) {
        if (e.from == null) {
                return;
            }
        if (e.regFlow == null) {
            return;
        }
        Long flowId = Long.parseLong(e.regFlow);
        int decimals = ChainService.getInstance(ChainEnum.BSC_TFC.name()).decimals();
            BigInteger tokens = e.tokens;
            BigDecimal amount = new BigDecimal(tokens.toString()).divide(BigDecimal.TEN.pow(decimals), decimals, RoundingMode.HALF_DOWN);
            DappFundFlowEntity fundFlow = dappFundFlowDao.selectByFromHashAndAndMemberId(e.log.getTransactionHash(), null,fromMember.getId());
            if(ObjectUtil.isNotEmpty(fundFlow) && 1 == fundFlow.getStatus()){
                if(18 == fundFlow.getType()){//认购贡献值 18
                    log.info("买入贡献值,{},金额:{}",fromAddress,amount);
                    if (fundFlow == null) {
                        List<DappFundFlowEntity> flows = dappFundFlowDao.selectFundFlowListByAddress(e.from, 1);
                        if (CollUtil.isEmpty(flows)) {
                            OnlineTransferUtil.addTransferRecord(e.from, e.to, amount, e.log.getTransactionHash(), DappTransferRecordEntity.TRANSFER_SOURCE_FLAG_ONLINE, "USDT");
                            log.info("本地无交易:{}", e.log.getTransactionHash());
        log.info("触发用户存储:{},金额:{},流水ID:{}",e.from,amount,flowId);
        // 账户是否已经注册
        DappMemberEntity fromMember = dappMemberService.findByAddress(e.from, null);
        if (fromMember == null) {
                            return;
                        }
                        for (DappFundFlowEntity flow : flows) {
                            if (flow.getStatus() == 1) {
                                if (amount.compareTo(flow.getAmount().multiply(flow.getNewestPrice()).setScale(4, RoundingMode.HALF_UP)) == 0) {
                                    fundFlow = flow;
                                    fundFlow.setFromHash(e.log.getTransactionHash());
                                    break;
                                }
                            }
                        }
                    }
                    if (fundFlow == null) {
        // 判断是否已经同步过了
        DappFundFlowEntity fundFlow = dappFundFlowDao.selectById(flowId);
        if (fundFlow != null && fundFlow.getStatus() != 1) {
                        return;
                    }
//                    fundFlow.setAmount(fundFlow.getAmount().negate());
                    // 更改状态为已同步
                    fundFlow.setStatus(2);
                    dappFundFlowDao.updateById(fundFlow);
                    //激活用户
                    fromMember.setActiveStatus(1);
                    dappMemberDao.updateById(fromMember);
                    //给上级直推奖励
//                    DappMemberEntity member = dappMemberDao.selectById(fromMember.getId());
//                    DappMemberEntity parent = dappMemberDao.selectMemberInfoByInviteId(member.getRefererId());
//
//                    if (ObjectUtil.isNotEmpty(parent)) {
//                        BigDecimal directProfit = TreeConstants.PUT_IN_AMOUNT.multiply(new BigDecimal("0.1"));
//                        dappWalletService.updateWalletCoinWithLock(directProfit, parent.getId(), 1);
//
//                        DappFundFlowEntity fundFlowPerk = new DappFundFlowEntity(parent.getId(), directProfit, 3, 2, null, null);
//                        dappFundFlowDao.insert(fundFlowPerk);
//                    }
                    //复投
//                    chainProducer.sendAchieveTreeMsg(fundFlow.getMemberId());
//                    if(ObjectUtil.isNotEmpty(fromMember.getRefererId())){
//                        DappMemberEntity dappMemberEntity = dappMemberDao.selectMemberInfoByInviteId(fromMember.getRefererId());
//                        if(ObjectUtil.isNotEmpty(dappMemberEntity)){
//                            chainProducer.sendNodeMsgLong(dappMemberEntity.getId());
//                        }
//                    }
                    chainProducer.sendNodeMsg(fundFlow.getId());
                    //发送推荐规则奖励
                    chainProducer.sendInvitePerkMsg(fundFlow.getId());
                    //发送节点投资
                    chainProducer.sendNodePerkMsg(fundFlow.getId());
//                    buyNodePerk(amount);
                }else if(13 == fundFlow.getType()){//认购节点 13
                    log.info("认购节点,{},金额:{}",fromAddress,amount);
//                    fundFlow.setAmount(fundFlow.getAmount().negate());
                    // 更改状态为已同步
                    fundFlow.setStatus(2);
                    dappFundFlowDao.updateById(fundFlow);
                    Long memberId = fundFlow.getMemberId();
                    DappMemberEntity dappMemberEntity = dappMemberDao.selectById(memberId);
                    Integer buyNode = dappMemberEntity.getBuyNode();
                    buyNode = buyNode + 1;
                    dappMemberEntity.setBuyNode(buyNode);
                    dappMemberDao.updateById(dappMemberEntity);
                }
            }else{
                return;
            }
        }
    }
        log.info("触发用户存储:{},金额:{},流水ID:{}",e.from,amount,flowId);
    public void buyNodePerk(BigDecimal amount){
        log.info("买入贡献值-平分总金额-{}",amount);
        /**
         * 获取节点平分百分比 perkPercent
         * 获取平分的份数 perKNum
         * 获取每一份的金额 perkAmount
         * 获取节点总数 buyNodeNum
         * 如果perKNum大于buyNodeNum,则每个人获得(amount * perkPercent)/ perKNum = perkAmount
         * 如果超出,再超出的人没有奖励
         * 新增一条记录
         */
        DataDictionaryCustom perkPercentDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
                DataDictionaryEnum.PERK_PERCENT.getType(),
                DataDictionaryEnum.PERK_PERCENT.getCode()
        DataDictionaryCustom dataDictionaryCustom = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
                DataDictionaryEnum.RELEASE_PERCENT.getType(),
                DataDictionaryEnum.RELEASE_PERCENT.getCode()
        );
        BigDecimal perkPercent = new BigDecimal(ObjectUtil.isEmpty(perkPercentDic) ? "10" : perkPercentDic.getValue()).multiply(new BigDecimal("0.01"));
        BigDecimal releasePercent = new BigDecimal(dataDictionaryCustom.getValue());
        DappStorage dappStorage = new DappStorage();
        dappStorage.setState(1);
        dappStorage.setAmount(amount);
        dappStorage.setReleasePercent(releasePercent);
        BigDecimal releaseAmount = amount.multiply(releasePercent).setScale(2, BigDecimal.ROUND_DOWN);
        dappStorage.setReleaseAmount(releaseAmount);
        dappStorageMapper.insert(dappStorage);
        DataDictionaryCustom perKNumDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
                DataDictionaryEnum.PERK_NUM.getType(),
                DataDictionaryEnum.PERK_NUM.getCode()
        );
        BigDecimal perKNum = new BigDecimal(ObjectUtil.isEmpty(perkPercentDic) ? "1000" : perKNumDic.getValue());
        BigDecimal perkAmount = amount.multiply(perkPercent).divide(perKNum, 8, BigDecimal.ROUND_DOWN);
        if(BigDecimal.ZERO.compareTo(perkAmount) >= 0){
            return;
        Long id = fundFlow.getId();
        Long memberId = fromMember.getId();
        /**
         * 发送直推8%
         */
        chainProducer.sendDirectPerkMsg(id);
        /**
         * DAO成员动态:
         *      * 1.直推1个拿2代,直推10个拿20代,直推15个拿30代,最高30代
         */
        chainProducer.sendMemberDynamicPerkMsg(id);
        /**
         *
         *      * 六、永动补偿池2%
         *      * 五、DAO永动激励池:6%
         *      * 四、DAO联盟委员会 :   5%  (50名全球DAO委员)
         */
        chainProducer.sendNodePerkMsg(id);
        /**
         *3.  成员升级
         *      *       DAO1:小区业绩30万/币  加权分红50%
         *      *       DAO2:小区业绩100万/币 加权分红30%
         *      *       DAO3:小区业绩500万/币加权分红20%
         */
        chainProducer.sendMemberLevel(memberId);
        }
        QueryWrapper<DappMemberEntity> objectQueryWrapper = new QueryWrapper<>();
        objectQueryWrapper.eq("buy_node",1);
        List<DappMemberEntity> dappMemberEntities = dappMemberDao.selectList(objectQueryWrapper);
        if(CollUtil.isEmpty(dappMemberEntities)){
            return;
        }
        for(DappMemberEntity dappMemberEntity : dappMemberEntities){
            dappWalletService.updateWalletCoinWithLock(perkAmount, dappMemberEntity.getId(), 1);
            DappFundFlowEntity fundFlow = new DappFundFlowEntity(
                    dappMemberEntity.getId(),
                    perkAmount,
                    14,
                    2,
                    BigDecimal.ZERO,
                    null);
            dappFundFlowDao.insert(fundFlow);
        }
        log.info("买入贡献值-总人数{},-每人金额{}",dappMemberEntities.size(),perkAmount);
    }
}
src/main/java/cc/mrbird/febs/dapp/service/impl/DappMemberServiceImpl.java
@@ -14,10 +14,13 @@
import cc.mrbird.febs.dapp.dto.PriceSettingDto;
import cc.mrbird.febs.dapp.entity.*;
import cc.mrbird.febs.dapp.enumerate.DataDictionaryEnum;
import cc.mrbird.febs.dapp.enumerate.MemberLevelEnum;
import cc.mrbird.febs.dapp.mapper.*;
import cc.mrbird.febs.dapp.service.DappMemberService;
import cc.mrbird.febs.dapp.vo.AdminSystemFeeVo;
import cc.mrbird.febs.dapp.vo.TeamDownVo;
import cc.mrbird.febs.dapp.vo.TeamListVo;
import cc.mrbird.febs.dapp.vo.TeamUpVo;
import cc.mrbird.febs.system.entity.User;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
@@ -36,6 +39,7 @@
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
 * @author
@@ -55,6 +59,7 @@
    private final DataDictionaryCustomMapper dataDictionaryCustomMapper;
    private final DappFundFlowDao dappFundFlowDao;
    private final DbMemberNodeMapper dbMemberNodeMapper;
    private final DappStorageMapper dappStorageMapper;
    @Override
    @Transactional(rollbackFor = Exception.class)
@@ -136,11 +141,6 @@
                if (parent == null) {
                    throw new FebsException("recommender is not exist");
                }
//                List<DappMemberEntity> child = dappMemberDao.selectChildMemberDirectOrNot(connectDto.getInviteId(), 1, null);
//                if (child.size() == 6) {
//                    throw new FebsException("Invite Code is Invalid");
//                }
            } else {
                connectDto.setInviteId(null);
            }
@@ -288,16 +288,14 @@
        member.setChainType(chainType);
        member.setAccountType(accountType);
        member.setActiveStatus(2);
        member.setNodeType(2);
        member.setLevel(MemberLevelEnum.DAO_0.getCode());
        dappMemberDao.insert(member);
        DappWalletCoinEntity walletCoin = new DappWalletCoinEntity();
        walletCoin.setMemberId(member.getId());
        dappWalletCoinDao.insert(walletCoin);
        DappWalletMineEntity walletMine = new DappWalletMineEntity();
        walletMine.setMemberId(member.getId());
        dappWalletMineDao.insert(walletMine);
        if (StrUtil.isEmpty(refererId)) {
            refererId = "0";
@@ -390,6 +388,93 @@
        return dbMemberNodeMapper.selectListInPage(dbMemberNode, page);
    }
    @Override
    public TeamUpVo teamUp() {
        Long memberId = LoginUserUtil.getAppUser().getId();
        TeamUpVo teamUpVo = new TeamUpVo();
        DappMemberEntity memberEntity = dappMemberDao.selectById(memberId);
        List<DappMemberEntity> directMembers = dappMemberDao.selectChildMemberDirectOrNot(memberEntity.getInviteId(), 1, null);
        if(CollUtil.isEmpty(directMembers)){
            teamUpVo.setTeamCnt(0);
            teamUpVo.setTeamCntAva(0);
            teamUpVo.setTeamAchieve(BigDecimal.ZERO);
            teamUpVo.setDirectCnt(0);
            teamUpVo.setDirectCntAva(0);
            teamUpVo.setDirectAchieve(BigDecimal.ZERO);
        }else{
            teamUpVo.setDirectCnt(CollUtil.isNotEmpty(directMembers) ? 0 : directMembers.size());
            List<DappMemberEntity> directCntAva = directMembers.stream().filter(dappMemberEntity -> dappMemberEntity.getActiveStatus() == 1).collect(Collectors.toList());
            teamUpVo.setDirectCntAva(CollUtil.isNotEmpty(directCntAva) ? 0 : directCntAva.size());
            List<Long> collectDirect = directCntAva.stream().map(DappMemberEntity::getId).collect(Collectors.toList());
            QueryWrapper<DappStorage> storageQueryWrapper = new QueryWrapper<>();
            storageQueryWrapper.in("member_id",collectDirect);
            storageQueryWrapper.eq("state",1);
            List<DappStorage> dappStoragesDirect = dappStorageMapper.selectList(storageQueryWrapper);
            BigDecimal directAchieve = dappStoragesDirect.stream()
                    .map(DappStorage::getAmount) // 映射amount到流中
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            teamUpVo.setDirectAchieve(directAchieve);
            List<DappMemberEntity> teamMembers = dappMemberDao.selectChildMemberDirectOrNot(memberEntity.getInviteId(), 2, null);
            teamUpVo.setTeamCnt(CollUtil.isNotEmpty(teamMembers) ? 0 : teamMembers.size());
            List<DappMemberEntity> teamCntAva = teamMembers.stream().filter(dappMemberEntity -> dappMemberEntity.getActiveStatus() == 1).collect(Collectors.toList());
            teamUpVo.setTeamCntAva(CollUtil.isNotEmpty(teamCntAva) ? 0 : teamCntAva.size());
            List<Long> collectTeam = teamCntAva.stream().map(DappMemberEntity::getId).collect(Collectors.toList());
            QueryWrapper<DappStorage> collectTeamWrapper = new QueryWrapper<>();
            collectTeamWrapper.in("member_id",collectTeam);
            collectTeamWrapper.eq("state",1);
            List<DappStorage> dappStoragesTeam = dappStorageMapper.selectList(collectTeamWrapper);
            BigDecimal teamAchieve = dappStoragesTeam.stream()
                    .map(DappStorage::getAmount) // 映射amount到流中
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            teamUpVo.setTeamAchieve(teamAchieve);
        }
        return teamUpVo;
    }
    @Override
    public List<TeamDownVo> teamDown() {
        Long memberId = LoginUserUtil.getAppUser().getId();
        List<TeamDownVo> objects = new ArrayList<>();
        DappMemberEntity memberEntity = dappMemberDao.selectById(memberId);
        List<DappMemberEntity> directMembers = dappMemberDao.selectChildMemberDirectOrNot(memberEntity.getInviteId(), 1, null);
        if(CollUtil.isNotEmpty(directMembers)){
            for(DappMemberEntity directMember : directMembers){
                TeamDownVo teamDownVo = new TeamDownVo();
                List<DappMemberEntity> teamMembers = dappMemberDao.selectChildMemberDirectOrNot(directMember.getInviteId(), 2, null);
                if(CollUtil.isEmpty(teamMembers)){
                    teamDownVo.setAddress(directMember.getAddress());
                    teamDownVo.setActiveCnt(0);
                    teamDownVo.setActiveAchieve(BigDecimal.ZERO);
                }else{
                    List<DappMemberEntity> teamCntAva = teamMembers.stream().filter(dappMemberEntity -> dappMemberEntity.getActiveStatus() == 1).collect(Collectors.toList());
                    List<Long> collectTeam = teamCntAva.stream().map(DappMemberEntity::getId).collect(Collectors.toList());
                    QueryWrapper<DappStorage> collectTeamWrapper = new QueryWrapper<>();
                    collectTeamWrapper.in("member_id",collectTeam);
                    collectTeamWrapper.eq("state",1);
                    List<DappStorage> dappStoragesTeam = dappStorageMapper.selectList(collectTeamWrapper);
                    BigDecimal teamAchieve = dappStoragesTeam.stream()
                            .map(DappStorage::getAmount) // 映射amount到流中
                            .reduce(BigDecimal.ZERO, BigDecimal::add);
                    teamDownVo.setAddress(directMember.getAddress());
                    teamDownVo.setActiveCnt(teamCntAva.size());
                    teamDownVo.setActiveAchieve(teamAchieve);
                }
                objects.add(teamDownVo);
            }
        }
        return objects;
    }
    public TeamListVo buildTeamMatrix(DappAchieveMemberTreeEntity node) {
        List<DappAchieveMemberTreeEntity> childNodes = dappAchieveMemberTreeDao.selectMatrixChildNode(node.getTopNode(), node.getTreeNode());
src/main/java/cc/mrbird/febs/dapp/service/impl/DappSystemServiceImpl.java
@@ -1,12 +1,11 @@
package cc.mrbird.febs.dapp.service.impl;
import cc.mrbird.febs.common.contants.AppContants;
import cc.mrbird.febs.common.utils.LoginUserUtil;
import cc.mrbird.febs.common.utils.RedisUtils;
import cc.mrbird.febs.dapp.dto.SystemDto;
import cc.mrbird.febs.dapp.entity.*;
import cc.mrbird.febs.dapp.enumerate.DataDictionaryEnum;
import cc.mrbird.febs.dapp.enumerate.InviteRule;
import cc.mrbird.febs.dapp.enumerate.NodeType;
import cc.mrbird.febs.dapp.enumerate.*;
import cc.mrbird.febs.dapp.mapper.*;
import cc.mrbird.febs.dapp.service.DappSystemService;
import cc.mrbird.febs.dapp.service.DappWalletService;
@@ -27,8 +26,7 @@
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.List;
import java.util.*;
import java.util.stream.Collectors;
/**
@@ -44,6 +42,7 @@
    private final RedisUtils redisUtils;
    private final DappFundFlowDao dappFundFlowDao;
    private final DappMemberDao dappMemberDao;
    private final DappStorageMapper dappStorageMapper;
    private final DappAchieveTreeDao dappAchieveTreeDao;
    private final DappAchieveMemberTreeDao dappAchieveMemberTreeDao;
@@ -225,7 +224,7 @@
        DappMemberEntity dappMemberEntityDirect = dappMemberDao.selectMemberInfoByInviteId(member.getRefererId());
        if(ObjectUtil.isNotEmpty(dappMemberEntityDirect)){
            Long id = dappMemberEntityDirect.getId();
            chainProducer.sendNodeMsgLong(id);
//            chainProducer.sendNodeMsgLong(id);
        }
        //如果添加的为右节点,那么进入判断
@@ -598,19 +597,28 @@
    @Override
    public void invitePerkMsg(Long id) {
        /**
         * 推荐规则:
         * 无直推奖励,推2个3层,3个6层,4个10层。1%见点奖(有效层级内,每个每1%),共10层,共%10。
         *     * 二、DAO成员动态:
         *      * 1.直推1个拿2代,直推10个拿20代,直推15个拿30代,最高30代
         *      * 2.   1-5代奖励7%
         *      *      6-10代奖励6%
         *      *      11-15代奖励5%
         *      *      15-20代奖励4%
         *      *      21-25代奖励4%
         *      *      26-30代奖励7%
         */
        DappFundFlowEntity dappFundFlowEntity = dappFundFlowDao.selectById(id);
        if(ObjectUtil.isEmpty(dappFundFlowEntity)){
            return;
        }
        if(DappFundFlowEntity.WITHDRAW_STATUS_AGREE != dappFundFlowEntity.getStatus()){
            return;
        }
        BigDecimal amount = dappFundFlowEntity.getAmount().abs();
        /**
         * 往上循环十层,判断每一层是否有见点奖
         * 往上循环30层,判断每一层是否有见点奖
         */
        Long memberId = dappFundFlowEntity.getMemberId();
        for(int i = 1;i <= 10;i++){
        for(int i = 1;i <= 30;i++){
            DappMemberEntity dappMemberEntity = dappMemberDao.selectById(memberId);
            String refererId = dappMemberEntity.getRefererId();
            //上级不存在,则停止循环。
@@ -666,73 +674,347 @@
    @Override
    public void nodePerkMsg(Long id) {
        DappFundFlowEntity dappFundFlowEntity = dappFundFlowDao.selectById(id);
        if(ObjectUtil.isEmpty(dappFundFlowEntity)){
        if(MoneyFlowEnum.CUN_CHU.getValue() != dappFundFlowEntity.getType()){
            return;
        }
        BigDecimal amount = dappFundFlowEntity.getAmount().abs();
        log.info("买入贡献值-平分总金额-{}",amount);
        if(DappFundFlowEntity.WITHDRAW_STATUS_AGREE != dappFundFlowEntity.getStatus()){
            return;
        }
        BigDecimal amount = dappFundFlowEntity.getAmount();
        /**
         * 获取节点平分百分比 perkPercent
         * 获取平分的份数 perKNum
         * 获取每一份的金额 perkAmount
         * 获取节点总数 buyNodeNum
         * 如果perKNum大于buyNodeNum,则每个人获得(amount * perkPercent)/ perKNum = perkAmount
         * 如果超出,再超出的人没有奖励
         * 激励池 6%
         */
        DataDictionaryCustom perkPercentDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
                DataDictionaryEnum.PERK_PERCENT.getType(),
                DataDictionaryEnum.PERK_PERCENT.getCode()
        BigDecimal jiliAmount = new BigDecimal(AppContants.DAO_JI_LI_PERCENT).multiply(amount);
        DataDictionaryCustom jiliChiDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
                DataDictionaryEnum.JILI_CHI.getType(),
                DataDictionaryEnum.JILI_CHI.getCode()
        );
        BigDecimal perkPercent = new BigDecimal(ObjectUtil.isEmpty(perkPercentDic) ? "10" : perkPercentDic.getValue()).multiply(new BigDecimal("0.01"));
        BigDecimal addJili = new BigDecimal(jiliChiDic.getValue()).add(jiliAmount).setScale(2,BigDecimal.ROUND_DOWN);
        jiliChiDic.setValue(addJili.toString());
        dataDictionaryCustomMapper.updateById(jiliChiDic);
        DataDictionaryCustom perKNumDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
                DataDictionaryEnum.PERK_NUM.getType(),
                DataDictionaryEnum.PERK_NUM.getCode()
        /**
         * 补偿池 2%
         */
        BigDecimal buchangAmount = new BigDecimal(AppContants.DAO_BU_CHANG_PERCENT).multiply(amount);
        DataDictionaryCustom buchangChiDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
                DataDictionaryEnum.BUCAHNG_CHI.getType(),
                DataDictionaryEnum.BUCAHNG_CHI.getCode()
        );
        BigDecimal perKNum = new BigDecimal(ObjectUtil.isEmpty(perKNumDic) ? "200" : perKNumDic.getValue());
        BigDecimal addBuchang = new BigDecimal(buchangChiDic.getValue()).add(buchangAmount).setScale(2,BigDecimal.ROUND_DOWN);
        buchangChiDic.setValue(addBuchang.toString());
        dataDictionaryCustomMapper.updateById(buchangChiDic);
        BigDecimal perkAmount = amount.multiply(perkPercent).divide(perKNum, 8, BigDecimal.ROUND_DOWN);
        if(BigDecimal.ZERO.compareTo(perkAmount) >= 0){
            return;
        }
        /**
         * DAO联盟委员会 :   5%
         */
        BigDecimal daoNodeAmountTotal = new BigDecimal(AppContants.DAO_NODE_PERCENT).multiply(amount);
        QueryWrapper<DappMemberEntity> objectQueryWrapper = new QueryWrapper<>();
        objectQueryWrapper.ge("buy_node",0);
        objectQueryWrapper.eq("node_type",1);
        List<DappMemberEntity> dappMemberEntities = dappMemberDao.selectList(objectQueryWrapper);
        if(CollUtil.isEmpty(dappMemberEntities)){
            return;
        }
        //奖励总份数
        BigDecimal totalPerkNum = BigDecimal.ZERO;
        for(DappMemberEntity dappMemberEntity : dappMemberEntities){
            //如果账号未激活,则无法领取收益
            if(1 != dappMemberEntity.getActiveStatus()){
                continue;
        BigDecimal daoNodeAmount = daoNodeAmountTotal.divide(new BigDecimal(dappMemberEntities.size()),2,BigDecimal.ROUND_DOWN);
        for(DappMemberEntity nodeMember : dappMemberEntities){
            this.updateBalanceInsertFlow(
                    daoNodeAmount,
                    nodeMember.getId(),
                    MoneyFlowEnum.NODE_PERK.getValue(),
                    StrUtil.format(MoneyFlowEnum.NODE_PERK.getDescrition(),amount,dappMemberEntities.size(),daoNodeAmount));
            }
            BigDecimal buyNode = new BigDecimal(dappMemberEntity.getBuyNode());
            totalPerkNum = totalPerkNum.add(buyNode);
            if(perKNum.compareTo(totalPerkNum) < 0){
    }
    @Override
    public void directPerkMsg(Long id) {
        DappFundFlowEntity dappFundFlowEntity = dappFundFlowDao.selectById(id);
        if(MoneyFlowEnum.CUN_CHU.getValue() != dappFundFlowEntity.getType()){
                return;
            }
            //奖励金额
            BigDecimal memberPerk = perkAmount.multiply(buyNode);
            if(BigDecimal.ZERO.compareTo(memberPerk) >= 0){
                continue;
        if(DappFundFlowEntity.WITHDRAW_STATUS_AGREE != dappFundFlowEntity.getStatus()){
            return;
            }
            dappWalletService.updateWalletCoinWithLock(memberPerk, dappMemberEntity.getId(), 1);
            DappFundFlowEntity fundFlow = new DappFundFlowEntity(
                    dappMemberEntity.getId(),
                    memberPerk,
                    14,
        Long memberId = dappFundFlowEntity.getMemberId();
        DappMemberEntity dappMemberEntity = dappMemberDao.selectById(memberId);
        if(ObjectUtil.isEmpty(dappMemberEntity)){
            return;
        }
        if(ObjectUtil.isEmpty(dappMemberEntity.getRefererId())){
            return;
        }
        DappMemberEntity directMember = dappMemberDao.selectMemberInfoByInviteId(dappMemberEntity.getRefererId());
        if(ObjectUtil.isEmpty(directMember)){
            return;
        }
        BigDecimal amount = dappFundFlowEntity.getAmount();
        /*
            直推 8%
         */
        BigDecimal directAmount = new BigDecimal(AppContants.DIRECT_PERCENT).multiply(amount);
        if(BigDecimal.ZERO.compareTo(directAmount) >= 0){
            return;
        }
        this.updateBalanceInsertFlow(
                directAmount,
                directMember.getId(),
                MoneyFlowEnum.DIRECT_PERK.getValue(),
                StrUtil.format(MoneyFlowEnum.DIRECT_PERK.getDescrition(),amount,directAmount));
    }
    @Override
    public void updateBalanceInsertFlow (BigDecimal daoNodeAmount,Long memberId,Integer type,String description){
        if(BigDecimal.ZERO.compareTo(daoNodeAmount) > 0){
            return;
        }
        DappMemberEntity dappMemberEntity = dappMemberDao.selectById(memberId);
        if(ObjectUtil.isEmpty(dappMemberEntity)){
            return;
        }
        if(1 != dappMemberEntity.getActiveStatus()){
            return;
        }
        //减少用户的总额度
        BigDecimal usdtBalance = dappMemberEntity.getUsdtBalance();
        if(BigDecimal.ZERO.compareTo(usdtBalance) >= 0){
            return;
        }
        if(daoNodeAmount.compareTo(usdtBalance) >= 0){
            daoNodeAmount = usdtBalance;
            usdtBalance = BigDecimal.ZERO;
        }else{
            usdtBalance = usdtBalance.subtract(daoNodeAmount);
        }
        //总额度为0,用户变成未激活
        if(BigDecimal.ZERO.compareTo(usdtBalance) >= 0){
            dappMemberEntity.setActiveStatus(2);
            //更新用户所有的业绩为已失效
            QueryWrapper<DappStorage> objectQueryWrapper = new QueryWrapper<>();
            objectQueryWrapper.eq("member_id",memberId);
            objectQueryWrapper.eq("state",1);
            List<DappStorage> dappStorages = dappStorageMapper.selectList(objectQueryWrapper);
            if(CollUtil.isNotEmpty(dappStorages)){
                for(DappStorage dappStorage : dappStorages){
                    dappStorage.setState(2);
                    dappStorageMapper.updateById(dappStorage);
                }
            }
        }
        dappMemberEntity.setUsdtBalance(usdtBalance);
        dappMemberDao.updateById(dappMemberEntity);
        dappWalletService.updateWalletCoinWithLock(daoNodeAmount, memberId, 1);
        DappFundFlowEntity nodeFlow = new DappFundFlowEntity(
                memberId,
                daoNodeAmount,
                type,
                    2,
                    BigDecimal.ZERO,
                    null);
            dappFundFlowDao.insert(fundFlow);
                description);
        dappFundFlowDao.insert(nodeFlow);
        }
        log.info("买入贡献值-总人数{},-每人金额{}",dappMemberEntities.size(),perkAmount);
    /**
     *
     *   3.  DAO成员团队奖:5%加权分红(people数量)
     *       DAO1:小区业绩30万/币  加权分红50%
     *       DAO2:小区业绩100万/币 加权分红30%
     *       DAO3:小区业绩500万/币加权分红20%
     */
    @Override
    public void teamPerk(Long id) {
        DappFundFlowEntity dappFundFlowEntity = dappFundFlowDao.selectById(id);
        if(MoneyFlowEnum.CUN_CHU.getValue() != dappFundFlowEntity.getType()){
            return;
        }
        if(DappFundFlowEntity.WITHDRAW_STATUS_AGREE != dappFundFlowEntity.getStatus()){
            return;
        }
        BigDecimal amount = dappFundFlowEntity.getAmount();
        //5%加权分红(people数量)
        BigDecimal totalAmount = amount.multiply(new BigDecimal(AppContants.DAO_TEAM_PERK_PERCENT)).setScale(2, BigDecimal.ROUND_DOWN);
        QueryWrapper<DappMemberEntity> daoOneQuery = new QueryWrapper<>();
        daoOneQuery.eq("level", MemberLevelEnum.DAO_1.getCode());
        List<DappMemberEntity> daoOnes = dappMemberDao.selectList(daoOneQuery);
        if(CollUtil.isNotEmpty(daoOnes)){
            BigDecimal bigDecimal = totalAmount.multiply(new BigDecimal("0.5")).setScale(2, BigDecimal.ROUND_DOWN);
            //每人平分数量
            BigDecimal divide = bigDecimal.divide(new BigDecimal(daoOnes.size()), 2, BigDecimal.ROUND_DOWN);
            for(DappMemberEntity memberEntity : daoOnes){
                this.updateBalanceInsertFlow(
                        divide,
                        memberEntity.getId(),
                        MoneyFlowEnum.TEAM_ONE_PERK.getValue(),
                        StrUtil.format(MoneyFlowEnum.TEAM_ONE_PERK.getDescrition(),divide));
            }
        }
        QueryWrapper<DappMemberEntity> daoTwoQuery = new QueryWrapper<>();
        daoTwoQuery.eq("level", MemberLevelEnum.DAO_2.getCode());
        List<DappMemberEntity> daoTwos = dappMemberDao.selectList(daoTwoQuery);
        if(CollUtil.isNotEmpty(daoTwos)){
            BigDecimal bigDecimal = totalAmount.multiply(new BigDecimal("0.3")).setScale(2, BigDecimal.ROUND_DOWN);
            //每人平分数量
            BigDecimal divide = bigDecimal.divide(new BigDecimal(daoTwos.size()), 2, BigDecimal.ROUND_DOWN);
            for(DappMemberEntity memberEntity : daoTwos){
                this.updateBalanceInsertFlow(
                        divide,
                        memberEntity.getId(),
                        MoneyFlowEnum.TEAM_TWO_PERK.getValue(),
                        StrUtil.format(MoneyFlowEnum.TEAM_TWO_PERK.getDescrition(),divide));
            }
        }
        QueryWrapper<DappMemberEntity> daoThreeQuery = new QueryWrapper<>();
        daoThreeQuery.eq("level", MemberLevelEnum.DAO_2.getCode());
        List<DappMemberEntity> daoThrees = dappMemberDao.selectList(daoThreeQuery);
        if(CollUtil.isNotEmpty(daoThrees)){
            BigDecimal bigDecimal = totalAmount.multiply(new BigDecimal("0.2")).setScale(2, BigDecimal.ROUND_DOWN);
            //每人平分数量
            BigDecimal divide = bigDecimal.divide(new BigDecimal(daoThrees.size()), 2, BigDecimal.ROUND_DOWN);
            for(DappMemberEntity memberEntity : daoThrees){
                this.updateBalanceInsertFlow(
                        divide,
                        memberEntity.getId(),
                        MoneyFlowEnum.TEAM_THREE_PERK.getValue(),
                        StrUtil.format(MoneyFlowEnum.TEAM_THREE_PERK.getDescrition(),divide));
            }
        }
    }
    @Override
    public void MemberLevel(Long id) {
        DappMemberEntity dappMemberEntity = dappMemberDao.selectById(id);
        if(StrUtil.isEmpty(dappMemberEntity.getRefererIds())){
            return;
        }
        //获取全部上级
        ArrayList<DappMemberEntity> activeMembers = new ArrayList<>();
        List<String> refererIds = Arrays.asList(StrUtil.split(",", dappMemberEntity.getRefererIds()));
        for(String inviteId : refererIds){
            DappMemberEntity memberEntity = dappMemberDao.selectMemberInfoByInviteId(inviteId);
            if(ObjectUtil.isNotEmpty(memberEntity)){
                activeMembers.add(memberEntity);
            }
        }
        if(CollUtil.isEmpty(activeMembers)){
            return;
        }
        for(DappMemberEntity activeMember : activeMembers){
            //获取每一个上级的所有直推,分辨大小区是否满足业绩需求
            List<DappMemberEntity> directMembers = dappMemberDao.selectChildMemberDirectOrNot(activeMember.getInviteId(), 1, null);
            if(CollUtil.isEmpty(directMembers)){
                continue;
            }
            if(directMembers.size() < 2){
                continue;
            }
            //获取activeMember的每一个直推的团队有效业绩
            HashMap<Long, BigDecimal> daXiaoQu = new HashMap<>();
            for(DappMemberEntity directMember : directMembers){
                //每一个直推的团队
                List<DappMemberEntity> direct = dappMemberDao.selectChildMemberDirectOrNot(directMember.getInviteId(), 2, null);
                if(CollUtil.isEmpty(direct)){
                    continue;
                }
                //获取直推的团队的全部有效业绩
                List<Long> collect = direct.stream().map(DappMemberEntity::getId).collect(Collectors.toList());
                QueryWrapper<DappStorage> storageQueryWrapper = new QueryWrapper<>();
                storageQueryWrapper.in("member_id",collect);
                storageQueryWrapper.eq("state",1);
                List<DappStorage> dappStorages = dappStorageMapper.selectList(storageQueryWrapper);
                if(CollUtil.isEmpty(dappStorages)){
                    continue;
                }
                BigDecimal directAchieve = dappStorages.stream()
                        .map(DappStorage::getAmount) // 映射amount到流中
                        .reduce(BigDecimal.ZERO, BigDecimal::add);
                daXiaoQu.put(directMember.getId(),directAchieve);
            }
            if(daXiaoQu.isEmpty()){
                continue;
            }
            //输出小区的总业绩
            BigDecimal sum = sumExcludingMax(daXiaoQu);
            BigDecimal dao_1_levelAchieve = new BigDecimal(MemberLevelEnum.DAO_1.getLevelAchieve());
            BigDecimal dao_2_levelAchieve = new BigDecimal(MemberLevelEnum.DAO_2.getLevelAchieve());
            BigDecimal dao_3_levelAchieve = new BigDecimal(MemberLevelEnum.DAO_3.getLevelAchieve());
            if(sum.compareTo(dao_3_levelAchieve) >= 0){
                activeMember.setLevel(MemberLevelEnum.DAO_3.getCode());
                dappMemberDao.updateById(activeMember);
            }else if(sum.compareTo(dao_2_levelAchieve) >= 0 && sum.compareTo(dao_3_levelAchieve) < 0){
                activeMember.setLevel(MemberLevelEnum.DAO_2.getCode());
                dappMemberDao.updateById(activeMember);
            }else if(sum.compareTo(dao_1_levelAchieve) >= 0 && sum.compareTo(dao_2_levelAchieve) < 0){
                activeMember.setLevel(MemberLevelEnum.DAO_1.getCode());
                dappMemberDao.updateById(activeMember);
            }else{
                activeMember.setLevel(MemberLevelEnum.DAO_0.getCode());
                dappMemberDao.updateById(activeMember);
            }
        }
    }
    /**
     * 计算HashMap中除最大值以外的数据的累计和
     *
     * @param map 包含Long作为key和BigDecimal作为value的HashMap
     * @return 除最大值以外的数据的累计和
     * @throws NullPointerException 如果HashMap为空,则抛出此异常
     */
    public static BigDecimal sumExcludingMax(HashMap<Long, BigDecimal> map) {
        if (map == null) {
            throw new NullPointerException("HashMap cannot be null");
        }
        // 使用Stream API找到最大的BigDecimal值及其对应的key
        Optional<Map.Entry<Long, BigDecimal>> maxEntry = map.entrySet().stream()
                .max((e1, e2) -> e1.getValue().compareTo(e2.getValue()));
        // 检查是否找到了最大值
        if (maxEntry.isPresent()) {
            // 移除最大值对应的键值对
            map.remove(maxEntry.get().getKey());
            // 计算剩余数据的累计和
            BigDecimal sumOfRemaining = map.entrySet().stream()
                    .map(Map.Entry::getValue)
                    .reduce(BigDecimal.ZERO, BigDecimal::add);
            // 返回累计和
            return sumOfRemaining;
        } else {
            // 如果没有找到最大值(即HashMap为空),则返回BigDecimal.ZERO
            return BigDecimal.ZERO;
        }
    }
    // 主函数,用于测试
    public static void main(String[] args) {
        HashMap<Long, BigDecimal> map = new HashMap<>();
        map.put(1L, new BigDecimal("100.00"));
        map.put(2L, new BigDecimal("200.00"));
        map.put(4L, new BigDecimal("200.00"));
        map.put(3L, new BigDecimal("50.00"));
        BigDecimal sum = sumExcludingMax(map);
        System.out.println("Sum of remaining values excluding the maximum: " + sum);
    }
}
src/main/java/cc/mrbird/febs/dapp/service/impl/DappWalletServiceImpl.java
@@ -8,6 +8,8 @@
import cc.mrbird.febs.dapp.dto.*;
import cc.mrbird.febs.dapp.entity.*;
import cc.mrbird.febs.dapp.enumerate.DataDictionaryEnum;
import cc.mrbird.febs.dapp.enumerate.MemberLevelEnum;
import cc.mrbird.febs.dapp.enumerate.MoneyFlowEnum;
import cc.mrbird.febs.dapp.enumerate.NodeType;
import cc.mrbird.febs.dapp.mapper.*;
import cc.mrbird.febs.dapp.service.DappWalletService;
@@ -30,7 +32,6 @@
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;
/**
 * @author
@@ -61,70 +62,20 @@
        DappMemberEntity memberInfo = dappMemberDao.selectById(member.getId());
        WalletInfoVo walletInfo = new WalletInfoVo();
        List<DappMemberEntity> inviteList = dappMemberDao.selectChildMemberDirectOrNot(member.getInviteId(), 1, null);
        List<DappMemberEntity> direct = dappMemberDao.selectChildMemberDirectOrNot(member.getInviteId(), 2, null);
        DappWalletCoinEntity walletCoin = dappWalletCoinDao.selectByMemberId(member.getId());
        DappWalletMineEntity walletMine = dappWalletMineDao.selectByMemberId(member.getId());
        DappMineDataEntity mineData = dappSystemDao.selectMineDataForOne();
        walletInfo.setDirectCnt(CollUtil.isEmpty(direct) ? 0 : direct.size());
        walletInfo.setInviteCnt(CollUtil.isEmpty(inviteList) ? 0 : inviteList.size());
        List<DappMemberEntity> collect = dappMemberDao.selectChildMemberDirectOrNot(member.getInviteId(), 1, 1);
        walletInfo.setActiveDirect(CollUtil.isEmpty(collect) ? 0 : collect.size());
        List<DappMemberEntity> collectTeam = direct.stream().filter(dappMemberEntity -> dappMemberEntity.getActiveStatus() == 1).collect(Collectors.toList());
        walletInfo.setActiveCnt(CollUtil.isEmpty(collectTeam) ? 0 : collectTeam.size());
//        walletInfo.setInviteId(member.getActiveStatus() == 1 ? member.getInviteId() : "-");
        walletInfo.setInviteId(member.getInviteId());
        walletInfo.setBalance(walletCoin.getAvailableAmount());
        walletInfo.setHasBuy(memberInfo.getActiveStatus());
        QueryWrapper<DbMemberNode> nodeQueryWrapper = new QueryWrapper<>();
        nodeQueryWrapper.eq("member_id",member.getId());
        nodeQueryWrapper.eq("work_state", DbMemberNode.STATE_TWO);
        List<DbMemberNode> dbMemberNodes = dbMemberNodeMapper.selectList(nodeQueryWrapper);
        walletInfo.setOutCnt(CollUtil.isEmpty(dbMemberNodes) ? 0 : dbMemberNodes.size());
//        walletInfo.setOutCnt(memberInfo.getOutCnt());
        walletInfo.setProfit(dappFundFlowDao.selectProfitAmountByMemberId(member.getId()));
        walletInfo.setTfcBalance(walletMine.getAvailableAmount());
        walletInfo.setSafePool(mineData.getSafePool());
        DataDictionaryCustom buyNodeAmountDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
                DataDictionaryEnum.BUY_NODE_AMOUNT.getType(),
                DataDictionaryEnum.BUY_NODE_AMOUNT.getCode()
        walletInfo.setLevelName(MemberLevelEnum.DAO_0.getLevelType(member.getLevel()));
        walletInfo.setNodeType(member.getNodeType());
        walletInfo.setActiveStatus(member.getActiveStatus());
        walletInfo.setUsdtBalance(member.getUsdtBalance());
        DataDictionaryCustom withdrawPercentDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
                DataDictionaryEnum.WITHDRAW_PERCENT.getType(),
                DataDictionaryEnum.WITHDRAW_PERCENT.getCode()
        );
        BigDecimal buyNodeAmount = new BigDecimal(StrUtil.isEmpty(buyNodeAmountDic.getValue()) ? "100" : buyNodeAmountDic.getValue());
        walletInfo.setBuyNodeAmount(buyNodeAmount);
        DataDictionaryCustom buyNodeCodeCntDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
                DataDictionaryEnum.BUY_NODE_CNT.getType(),
                DataDictionaryEnum.BUY_NODE_CNT.getCode()
        );
        BigDecimal buyNodeCodeCnt = new BigDecimal(StrUtil.isEmpty(buyNodeCodeCntDic.getValue()) ? "3" : buyNodeCodeCntDic.getValue());
        walletInfo.setBuyNodeCnt(buyNodeCodeCnt);
        walletInfo.setBuyNode(ObjectUtil.isEmpty(memberInfo.getBuyNode()) ? 0 : memberInfo.getBuyNode());
        BigDecimal bigDecimal = dappFundFlowDao.selectSumAmountByMemberIdAndType(member.getId(), 14);
        walletInfo.setBuyNodePerk(bigDecimal);
        int i = memberInfo.getBuyNode() * 2000;
        int teamCnt = CollUtil.isEmpty(direct) ? 0 : direct.size();
        int i1 = teamCnt * 15;
        QueryWrapper<DbMemberNode> objectQueryWrapper = new QueryWrapper<>();
        objectQueryWrapper.eq("member_id",member.getId());
        List<DbMemberNode> dbMemberNodes1 = dbMemberNodeMapper.selectList(objectQueryWrapper);
        walletInfo.setScoreCnt(i+i1+(CollUtil.isEmpty(dbMemberNodes1) ? 0 : dbMemberNodes1.size())*300);
//        Integer activeStatus = ObjectUtil.isEmpty(member.getActiveStatus()) ? 2 : member.getActiveStatus();
//        if(1 == activeStatus){
//            int i = memberInfo.getBuyNode() * 2000;
//            int teamCnt = CollUtil.isEmpty(direct) ? 0 : direct.size();
//            int i1 = teamCnt * 15;
//            QueryWrapper<DbMemberNode> objectQueryWrapper = new QueryWrapper<>();
//            objectQueryWrapper.eq("member_id",member.getId());
//            List<DbMemberNode> dbMemberNodes1 = dbMemberNodeMapper.selectList(objectQueryWrapper);
//            walletInfo.setScoreCnt(i+i1+(CollUtil.isEmpty(dbMemberNodes1) ? 0 : dbMemberNodes1.size())*300);
//        }else{
//            walletInfo.setScoreCnt(0);
//        }
        BigDecimal withdrawPercent = new BigDecimal(withdrawPercentDic.getValue());
        walletInfo.setWithdrawPercent(withdrawPercent);
        return walletInfo;
    }
@@ -139,8 +90,6 @@
            dappFundFlowEntity.setType(recordInPageDto.getType());
        }
        dappFundFlowEntity.setMemberId(member.getId());
//        dappFundFlowEntity.setStatus(2);
        IPage<DappFundFlowEntity> records = dappFundFlowDao.selectInPage(page, dappFundFlowEntity);
        return records.getRecords();
    }
@@ -267,15 +216,15 @@
            throw new FebsException("Balance Not Enough");
        }
//        DappWalletMineEntity walletMine = dappWalletMineDao.selectByMemberId(member.getId());
//        if (walletMine.getAvailableAmount().compareTo(withdrawDto.getFee()) < 0) {
//            throw new FebsException("Fee Not Enough");
//        }
        updateWalletCoinWithLock(withdrawDto.getAmount(), member.getId(), 2);
//        updateWalletMineWithLock(withdrawDto.getFee(), member.getId(), 2);
        DappFundFlowEntity fundFlow = new DappFundFlowEntity(member.getId(), withdrawDto.getAmount().negate(), 21, 1, withdrawDto.getFee(), null);
        DappFundFlowEntity fundFlow = new DappFundFlowEntity(
                member.getId(),
                withdrawDto.getAmount().negate(),
                21,
                1,
                withdrawDto.getFee(),
                null);
        dappFundFlowDao.insert(fundFlow);
        MemberCoinWithdrawEntity memberCoinWithdraw = new MemberCoinWithdrawEntity();
@@ -400,42 +349,28 @@
            throw new FebsException("功能升级中");
        }
        member = dappMemberDao.selectById(member.getId());
//        int buyNode = ObjectUtil.isEmpty(member.getBuyNode()) ? 0 : 1;
        int buyNode = member.getBuyNode();
        DataDictionaryCustom buyNodeCodeCntDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
                DataDictionaryEnum.BUY_NODE_CNT.getType(),
                DataDictionaryEnum.BUY_NODE_CNT.getCode()
        );
        if (buyNode >= Integer.parseInt(buyNodeCodeCntDic.getValue())) {
            throw new FebsException("Do not repeat purchase");
        BigDecimal amount = transferDto.getAmount();
        if(BigDecimal.ZERO.compareTo(amount) >= 0){
            throw new FebsException("请输入正确的存储数量");
        }
        /**
         * 限购总数200
         * 检查一个BigDecimal是否能被500整除
         */
        DataDictionaryCustom perKNumDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
                DataDictionaryEnum.PERK_NUM.getType(),
                DataDictionaryEnum.PERK_NUM.getCode()
        );
        int perKNum = Integer.parseInt(ObjectUtil.isEmpty(perKNumDic) ? "200" : perKNumDic.getValue());
        List<DappMemberEntity> dappMemberEntities = dappMemberDao.selectList(null);
        if(CollUtil.isNotEmpty(dappMemberEntities)){
            int sum1 = dappMemberEntities.stream().mapToInt(DappMemberEntity::getBuyNode).sum();
            if(perKNum < sum1 + 1){
                throw new FebsException("节点已售完");
            }
        BigDecimal bigDecimal = new BigDecimal("500");
        BigDecimal remainder = amount.remainder(bigDecimal);
        if(remainder.compareTo(BigDecimal.ZERO) != 0){
            throw new FebsException("存储数量必须是"+bigDecimal+"的整数倍");
        }
        if (ObjectUtil.isEmpty(transferDto.getId())) {
            DappFundFlowEntity fundFlow = new DappFundFlowEntity(
                    member.getId(),
                    transferDto.getAmount().negate(),
                    13,
                    transferDto.getAmount().abs(),
                    MoneyFlowEnum.CUN_CHU.getValue(),
                    1,
                    BigDecimal.ZERO,
                    transferDto.getTxHash());
                    StrUtil.format(MoneyFlowEnum.CUN_CHU.getDescrition(),amount));
            dappFundFlowDao.insert(fundFlow);
            return fundFlow.getId();
        } else {
@@ -446,7 +381,6 @@
            if ("success".equals(transferDto.getFlag())) {
                flow.setFromHash(transferDto.getTxHash());
                dappFundFlowDao.updateById(flow);
            } else {
                if (flow.getStatus() == 1) {
                    dappFundFlowDao.deleteById(transferDto.getId());
src/main/java/cc/mrbird/febs/dapp/vo/TeamDownVo.java
New file
@@ -0,0 +1,26 @@
package cc.mrbird.febs.dapp.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
/**
 * @author wzy
 * @date 2022-06-06
 **/
@Data
@ApiModel(value = "TeamDownVo", description = "团队列表接口返回参数类")
public class TeamDownVo {
    @ApiModelProperty(value = "直推地址")
    private String address;
    @ApiModelProperty(value = "有效人数")
    private int activeCnt;
    @ApiModelProperty(value = "有效业绩")
    private BigDecimal activeAchieve;
}
src/main/java/cc/mrbird/febs/dapp/vo/TeamUpVo.java
New file
@@ -0,0 +1,35 @@
package cc.mrbird.febs.dapp.vo;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import java.math.BigDecimal;
/**
 * @author wzy
 * @date 2022-06-06
 **/
@Data
@ApiModel(value = "TeamUpVo", description = "团队列表接口返回参数类")
public class TeamUpVo {
    @ApiModelProperty(value = "团队人数")
    private int teamCnt;
    @ApiModelProperty(value = "直推人数")
    private int directCnt;
    @ApiModelProperty(value = "有效团队人数")
    private int teamCntAva;
    @ApiModelProperty(value = "有效直推人数")
    private int directCntAva;
    @ApiModelProperty(value = "团队总业绩")
    private BigDecimal teamAchieve;
    @ApiModelProperty(value = "直推总业绩")
    private BigDecimal directAchieve;
}
src/main/java/cc/mrbird/febs/dapp/vo/WalletInfoVo.java
@@ -17,48 +17,22 @@
    @ApiModelProperty(value = "邀请码")
    private String inviteId;
    @ApiModelProperty(value = "粉丝")
    private Integer directCnt;
    @ApiModelProperty(value = "余额")
    private BigDecimal balance;
    @ApiModelProperty(value = "出局次数")
    private int outCnt;
    @ApiModelProperty(value = "会员层级")
    private String levelName;
    @ApiModelProperty(value = "收益")
    private BigDecimal profit;
    @ApiModelProperty(value = "是否节点 1-是 2-否")
    private Integer nodeType;
    @ApiModelProperty(value = "是否购买")
    private Integer hasBuy;
    @ApiModelProperty(value = "激活状态 1-已激活 2-未激活")
    private Integer activeStatus;
    @ApiModelProperty(value = "手续费")
    private BigDecimal tfcBalance;
    @ApiModelProperty(value = "提现费率")
    private BigDecimal withdrawPercent;
    @ApiModelProperty(value = "保险池")
    private BigDecimal safePool;
    @ApiModelProperty(value = "提现费率")
    private BigDecimal usdtBalance;
    @ApiModelProperty(value = "购买节点的金额")
    private BigDecimal buyNodeAmount;
    @ApiModelProperty(value = "购买节点的最大次数")
    private BigDecimal buyNodeCnt;
    @ApiModelProperty(value = "节点收益")
    private BigDecimal buyNodePerk;
    @ApiModelProperty(value = "是否是节点 1-是 0-否")
    private Integer buyNode;
    @ApiModelProperty(value = "直推数量")
    private Integer inviteCnt;
    @ApiModelProperty(value = "有效人数")
    private Integer activeCnt;
    @ApiModelProperty(value = "贡献值")
    private Integer scoreCnt;
    @ApiModelProperty(value = "有效直推")
    private Integer activeDirect;
}
src/main/java/cc/mrbird/febs/job/ChainSDMChargeRunner.java
@@ -27,7 +27,7 @@
    @Override
    public void run(ApplicationArguments args) throws Exception {
        long start = System.currentTimeMillis();
        log.info("区块链充值开始启动");
        log.info("区块链存储开始启动");
        Object incrementObj = redisUtils.get(AppContants.REDIS_KEY_BLOCK_ETH_INCREMENT_NUM_CHARGE);
        BigInteger newest = ChainService.getInstance(ChainEnum.BSC_TFC.name()).blockNumber();
@@ -43,7 +43,7 @@
        while (newest.subtract(block).compareTo(section) > -1) {
            BigInteger end = block.add(section);
            log.info("监听:[{} - {}]", block, end);
            ChainService.sdmChargeEventListener(block, end, bscCoinContractEvent, ChainEnum.BSC_TFC.name());
            ChainService.receivePeopleEventListener(block, end, bscCoinContractEvent, ChainEnum.BSC_TFC.name());
            block = block.add(section);
            if (block.compareTo(newest) > 0) {
@@ -51,9 +51,9 @@
            }
        }
        ChainService.sdmChargeEventListener(block, null, bscCoinContractEvent, ChainEnum.BSC_TFC.name());
        ChainService.receivePeopleEventListener(block, null, bscCoinContractEvent, ChainEnum.BSC_TFC.name());
        long end = System.currentTimeMillis();
        log.info("区块链滑点启动完成, 消耗时间{}", end - start);
        log.info("区块链存储启动完成, 消耗时间{}", end - start);
    }
}
src/main/java/cc/mrbird/febs/job/ChainSDMListenerJob.java
File was deleted
src/main/java/cc/mrbird/febs/job/ChainSDMRunner.java
File was deleted
src/main/java/cc/mrbird/febs/job/MatrixResetJob.java
File was deleted
src/main/java/cc/mrbird/febs/job/MatrixTreeInit.java
File was deleted
src/main/java/cc/mrbird/febs/job/ProfitDailyJob.java
@@ -1,77 +1,331 @@
package cc.mrbird.febs.job;
import cc.mrbird.febs.dapp.entity.DappMemberEntity;
import cc.mrbird.febs.dapp.entity.DappStorage;
import cc.mrbird.febs.dapp.entity.DataDictionaryCustom;
import cc.mrbird.febs.dapp.enumerate.DataDictionaryEnum;
import cc.mrbird.febs.dapp.enumerate.MoneyFlowEnum;
import cc.mrbird.febs.dapp.mapper.DappMemberDao;
import cc.mrbird.febs.dapp.mapper.DappStorageMapper;
import cc.mrbird.febs.dapp.mapper.DataDictionaryCustomMapper;
import cc.mrbird.febs.dapp.service.DappSystemService;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
@Slf4j
@Component
@ConditionalOnProperty(prefix = "system", name = "quartz-job", havingValue = "true")
@ConditionalOnProperty(prefix = "system", name = "charge-transfer", havingValue = "true")
public class ProfitDailyJob {
//    @Autowired
//    private DappMemberDao dappMemberDao;
//    @Autowired
//    private DappFundFlowDao dappFundFlowDao;
//    @Autowired
//    private DataDictionaryCustomMapper dataDictionaryCustomMapper;
//    @Autowired
//    private DappWalletService dappWalletService;
//
//    @Scheduled(cron = "0 0 0 * * ?")
//    public void profitDailyJob() {
//        log.info("每日产矿任务执行");
//        DataDictionaryCustom symbolPriceDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(DataDictionaryEnum.SYMBOL_PRICE.getType(), DataDictionaryEnum.SYMBOL_PRICE.getCode());
//        if (symbolPriceDic == null) {
//            log.info("未设置币种价格");
//            return;
//        }
//
//        DataDictionaryCustom rebateDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(DataDictionaryEnum.REBATE_PERCENT.getType(), DataDictionaryEnum.REBATE_PERCENT.getCode());
//        if (rebateDic == null) {
//            log.info("未设置每日产矿比例");
//            return;
//        }
//
//        BigDecimal symbolPrice = new BigDecimal(symbolPriceDic.getValue());
//        BigDecimal rebateRatio = new BigDecimal(rebateDic.getValue());
//
//        QueryWrapper<DappMemberEntity> query = new QueryWrapper<>();
//        query.eq("active_status", 1);
//        List<DappMemberEntity> members = dappMemberDao.selectList(query);
//        if (CollUtil.isEmpty(members)) {
//            return;
//        }
//
//        members.forEach(item -> {
//            QueryWrapper<DappFundFlowEntity> fundFlowQuery = new QueryWrapper<>();
//            fundFlowQuery.eq("member_id", item.getId());
//            fundFlowQuery.eq("type", 11);
//            List<DappFundFlowEntity> flows = dappFundFlowDao.selectList(fundFlowQuery);
//
//            BigDecimal sum = BigDecimal.ZERO;
//            if (CollUtil.isNotEmpty(flows)) {
//                double symbolSum = flows.stream().mapToDouble(flow -> flow.getAmount().doubleValue()).sum();
//                sum = symbolPrice.multiply(new BigDecimal(symbolSum));
//            }
//
//            if (CollUtil.isEmpty(flows) || TreeConstants.PUT_IN_AMOUNT.compareTo(sum) > 0) {
//                BigDecimal profitU = TreeConstants.PUT_IN_AMOUNT.multiply(rebateRatio.divide(BigDecimal.valueOf(100), 4, RoundingMode.HALF_DOWN));
//
//                BigDecimal remain = TreeConstants.PUT_IN_AMOUNT.subtract(sum);
//                if (remain.compareTo(profitU) < 0) {
//                    profitU = remain;
//                }
//
//                BigDecimal profitSymbol = profitU.divide(symbolPrice, 8, RoundingMode.HALF_DOWN);
//
//                dappWalletService.updateWalletMineWithLock(profitSymbol, item.getId(), 1);
//                DappFundFlowEntity fundFlow = new DappFundFlowEntity(item.getId(), profitSymbol, 11, 2, null, null);
//                dappFundFlowDao.insert(fundFlow);
//            }
//        });
//
//
//    }
    @Resource
    private DappSystemService dappSystemService;
    @Resource
    private DataDictionaryCustomMapper dataDictionaryCustomMapper;
    @Resource
    private DappStorageMapper dappStorageMapper;
    @Resource
    private DappMemberDao dappMemberDao;
    /**
     * 每天释放1%的静态释放
     */
    @Scheduled(cron = "0 0 0 * * ?")
    public void profitDailyJobThree() {
        QueryWrapper<DappStorage> objectQueryWrapper = new QueryWrapper<>();
        objectQueryWrapper.eq("state",1);
        List<DappStorage> dappStorages = dappStorageMapper.selectList(objectQueryWrapper);
        if(CollUtil.isEmpty(dappStorages)){
            return;
        }
        for(DappStorage storage : dappStorages){
            Long memberId = storage.getMemberId();
            BigDecimal releaseAmount = storage.getReleaseAmount();
            dappSystemService.updateBalanceInsertFlow(
                    releaseAmount,
                    memberId,
                    MoneyFlowEnum.STATIC_PERK.getValue(),
                    StrUtil.format(MoneyFlowEnum.STATIC_PERK.getDescrition(),releaseAmount));
        }
    }
    /**
     * 六、永动补偿池2%
     * 24小时内最后一名拿走池子50%
     * 倒数2-100名拿走池子50%平分(根据时间)
     *
     *
     * 五、DAO永动激励池:6%
     *  循环激励50%(每天下午17:00结算)
     * (其中50%给予当天大单排名激励前4名,40%、30%、20、10%;
     * 另外50% 给予当天直推总业绩排名激励前10名,第1名40%,2-4名30%,5-10名30%)
     */
    @Scheduled(cron = "0 0 0 * * ?")
    public void profitDailyJobOne() {
        DataDictionaryCustom buChangChiDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
                DataDictionaryEnum.BUCAHNG_CHI.getType(),
                DataDictionaryEnum.BUCAHNG_CHI.getCode()
        );
        //永动补偿池2%
        BigDecimal buChangAmountTotal = new BigDecimal(buChangChiDic.getValue()).setScale(2, BigDecimal.ROUND_DOWN);
        if(BigDecimal.ZERO.compareTo(buChangAmountTotal) >= 0){
            return;
        }
        //剩余金额
        BigDecimal surplusAmount = BigDecimal.ZERO;
        /**
         * 最后一名拿走池子50%
         */
        BigDecimal oneAmount = buChangAmountTotal.multiply(new BigDecimal("0.5")).setScale(2,BigDecimal.ROUND_DOWN);
        DateTime dateTime = DateUtil.offsetHour(new Date(), -24);
        DappStorage dappStorage = dappStorageMapper.selectOneByDateDesc(dateTime);
        if(ObjectUtil.isNotEmpty(dappStorage)){
            Long memberId = dappStorage.getMemberId();
            dappSystemService.updateBalanceInsertFlow(
                    oneAmount,
                    memberId,
                    MoneyFlowEnum.BU_CHANG_PERK.getValue(),
                    StrUtil.format(MoneyFlowEnum.BU_CHANG_PERK.getDescrition(),buChangAmountTotal,oneAmount));
            surplusAmount = surplusAmount.add(oneAmount);
        }
        /**
         * 倒数2-100名拿走池子50%平分(根据时间)
         */
        BigDecimal otherAmount = buChangAmountTotal.subtract(oneAmount);
        List<DappStorage> dappStorages = dappStorageMapper.selectListByDateDesc(dateTime);
        if(CollUtil.isNotEmpty(dappStorages)){
            BigDecimal otherAmountReal = otherAmount.divide(new BigDecimal(dappStorages.size())).setScale(2, BigDecimal.ROUND_DOWN);
            surplusAmount = surplusAmount.add(otherAmount);
            for(DappStorage storage : dappStorages){
                Long memberId = storage.getMemberId();
                dappSystemService.updateBalanceInsertFlow(
                        otherAmountReal,
                        memberId,
                        MoneyFlowEnum.BU_CHANG_PERK.getValue(),
                        StrUtil.format(MoneyFlowEnum.BU_CHANG_PERK.getDescrition(),buChangAmountTotal,oneAmount));
            }
        }
        buChangChiDic.setValue(buChangAmountTotal.subtract(surplusAmount).setScale(2,BigDecimal.ROUND_DOWN).toString());
        dataDictionaryCustomMapper.updateById(buChangChiDic);
    }
    /**
     * 五、DAO永动激励池:6%
     *  循环激励50%(每天下午17:00结算)
     * (其中50%给予当天大单排名激励前4名,40%、30%、20、10%;
     * 另外50% 给予当天直推总业绩排名激励前10名,第1名40%,2-4名30%,5-10名30%)
     */
    @Scheduled(cron = "0 0 17 * * ?")
    public void profitDailyJobTwo() {
        DataDictionaryCustom jiliChiDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
                DataDictionaryEnum.JILI_CHI.getType(),
                DataDictionaryEnum.JILI_CHI.getCode()
        );
        BigDecimal realAmount = BigDecimal.ZERO;
        //DAO永动激励池50%
        BigDecimal jiLiTotal = new BigDecimal(jiliChiDic.getValue()).multiply(new BigDecimal("0.5")).setScale(2, BigDecimal.ROUND_DOWN);
        if(BigDecimal.ZERO.compareTo(jiLiTotal) >= 0){
            return;
        }
        /**
         * 其中50%给予当天大单排名激励前4名,40%、30%、20、10%
         */
        BigDecimal daDanTotal = jiLiTotal.multiply(new BigDecimal("0.5")).setScale(2, BigDecimal.ROUND_DOWN);
        if(daDanTotal.compareTo(BigDecimal.ZERO) > 0){
            int oneCount = 4;
            int twoCount = 3;
            int threeCount = 2;
            int fourCount = 1;
            int count = oneCount + twoCount + threeCount + fourCount;
            //每一份的奖励数量
            BigDecimal everyAmount = daDanTotal.divide(new BigDecimal(count));
            if(everyAmount.compareTo(BigDecimal.ZERO) > 0){
                DappStorage dappStorageOne = dappStorageMapper.selectAmountByDesc(new Date(),0,1);
                if(ObjectUtil.isNotEmpty(dappStorageOne)){
                    BigDecimal multiply = everyAmount.multiply(new BigDecimal(oneCount));
                    dappSystemService.updateBalanceInsertFlow(
                            multiply,
                            dappStorageOne.getMemberId(),
                            MoneyFlowEnum.DA_DAN_JI_LI_PERK.getValue(),
                            StrUtil.format(MoneyFlowEnum.DA_DAN_JI_LI_PERK.getDescrition(),daDanTotal,multiply));
                    realAmount = realAmount.add(multiply);
                }
                DappStorage dappStorageTwo = dappStorageMapper.selectAmountByDesc(new Date(),1,1);
                if(ObjectUtil.isNotEmpty(dappStorageTwo)){
                    BigDecimal multiply = everyAmount.multiply(new BigDecimal(twoCount));
                    dappSystemService.updateBalanceInsertFlow(
                            multiply,
                            dappStorageTwo.getMemberId(),
                            MoneyFlowEnum.DA_DAN_JI_LI_PERK.getValue(),
                            StrUtil.format(MoneyFlowEnum.DA_DAN_JI_LI_PERK.getDescrition(),daDanTotal,multiply));
                    realAmount = realAmount.add(multiply);
                }
                DappStorage dappStorageThree = dappStorageMapper.selectAmountByDesc(new Date(),2,1);
                if(ObjectUtil.isNotEmpty(dappStorageThree)){
                    BigDecimal multiply = everyAmount.multiply(new BigDecimal(threeCount));
                    dappSystemService.updateBalanceInsertFlow(
                            multiply,
                            dappStorageThree.getMemberId(),
                            MoneyFlowEnum.DA_DAN_JI_LI_PERK.getValue(),
                            StrUtil.format(MoneyFlowEnum.DA_DAN_JI_LI_PERK.getDescrition(),daDanTotal,multiply));
                    realAmount = realAmount.add(multiply);
                }
                DappStorage dappStorageFour = dappStorageMapper.selectAmountByDesc(new Date(),3,1);
                if(ObjectUtil.isNotEmpty(dappStorageFour)){
                    BigDecimal multiply = everyAmount.multiply(new BigDecimal(fourCount));
                    dappSystemService.updateBalanceInsertFlow(
                            multiply,
                            dappStorageFour.getMemberId(),
                            MoneyFlowEnum.DA_DAN_JI_LI_PERK.getValue(),
                            StrUtil.format(MoneyFlowEnum.DA_DAN_JI_LI_PERK.getDescrition(),daDanTotal,multiply));
                    realAmount = realAmount.add(multiply);
                }
            }
        }
        /**
         * 另外50% 给予当天直推总业绩排名激励前10名,第1名40%,2-4名30%,5-10名30%
         */
        BigDecimal directTotal = jiLiTotal.multiply(new BigDecimal("0.5")).setScale(2, BigDecimal.ROUND_DOWN);
        /**
         * 存放直推业绩<上级的memberId,直推总业绩>
         */
        HashMap<Long, BigDecimal> map = new HashMap<>();
        List<DappStorage> dappStorages = dappStorageMapper.selectListByDate(new Date());
        if(CollUtil.isNotEmpty(dappStorages)){
            for(DappStorage dappStorage : dappStorages){
                DappMemberEntity member = dappMemberDao.selectById(dappStorage.getMemberId());
                if(StrUtil.isEmpty(member.getRefererId())){
                    continue;
                }
                DappMemberEntity memberRef = dappMemberDao.selectMemberInfoByInviteId(member.getRefererId());
                if(ObjectUtil.isEmpty(memberRef)){
                    continue;
                }
                Long id = memberRef.getId();
                if(map.containsKey(id)){
                    BigDecimal bigDecimal = map.get(id);
                    BigDecimal add = bigDecimal.add(dappStorage.getAmount());
                    map.put(id,add);
                }else{
                    map.put(id,dappStorage.getAmount());
                }
            }
        }
        /**
         * 获取这个map的直推总业绩前十,分发奖励
         */
        if(!map.isEmpty()){
            // 使用Stream API按照BigDecimal从大到小排序
            List<Map.Entry<Long, BigDecimal>> topTenEntries = map.entrySet().stream()
                    .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
                    .limit(10)
                    .collect(Collectors.toList());
            int startNum = 1;
            for (Map.Entry<Long, BigDecimal> entry : topTenEntries) {
                Long memberId = entry.getKey();
                BigDecimal directAchieve = entry.getValue();
                //第一名
                if(startNum == 1){
                    BigDecimal bigDecimal = directTotal.multiply(new BigDecimal("0.4")).setScale(2, BigDecimal.ROUND_DOWN);
                    dappSystemService.updateBalanceInsertFlow(
                            bigDecimal,
                            memberId,
                            MoneyFlowEnum.ZHI_TUI_JI_LI_PERK.getValue(),
                            StrUtil.format(MoneyFlowEnum.ZHI_TUI_JI_LI_PERK.getDescrition(),directAchieve,startNum,bigDecimal));
                    realAmount = realAmount.add(bigDecimal);
                }else if(startNum > 1 && startNum <=4){
                    BigDecimal bigDecimal = directTotal.multiply(new BigDecimal("0.3")).setScale(2, BigDecimal.ROUND_DOWN);
                    BigDecimal divide = bigDecimal.divide(new BigDecimal("3"), 2, BigDecimal.ROUND_DOWN);
                    dappSystemService.updateBalanceInsertFlow(
                            divide,
                            memberId,
                            MoneyFlowEnum.ZHI_TUI_JI_LI_PERK.getValue(),
                            StrUtil.format(MoneyFlowEnum.ZHI_TUI_JI_LI_PERK.getDescrition(),directAchieve,startNum,divide));
                    realAmount = realAmount.add(divide);
                }else{
                    BigDecimal bigDecimal = directTotal.multiply(new BigDecimal("0.3")).setScale(2, BigDecimal.ROUND_DOWN);
                    BigDecimal divide = bigDecimal.divide(new BigDecimal("6"), 2, BigDecimal.ROUND_DOWN);
                    dappSystemService.updateBalanceInsertFlow(
                            divide,
                            memberId,
                            MoneyFlowEnum.ZHI_TUI_JI_LI_PERK.getValue(),
                            StrUtil.format(MoneyFlowEnum.ZHI_TUI_JI_LI_PERK.getDescrition(),directAchieve,startNum,divide));
                    realAmount = realAmount.add(divide);
                }
                startNum = startNum + 1;
            }
        }
        BigDecimal subtract = new BigDecimal(jiliChiDic.getValue()).subtract(realAmount);
        jiliChiDic.setValue(subtract.toString());
        dataDictionaryCustomMapper.updateById(jiliChiDic);
    }
    public static void main(String[] args) {
        DateTime dateTime = DateUtil.offsetHour(new Date(), -24);
        System.out.println(dateTime);
        // 创建一个HashMap示例
        HashMap<Long, BigDecimal> map = new HashMap<>();
        map.put(1L, new BigDecimal("100.00"));
        map.put(2L, new BigDecimal("200.00"));
        map.put(3L, new BigDecimal("50.00"));
        map.put(4L, new BigDecimal("300.00"));
        map.put(5L, new BigDecimal("150.00"));
        map.put(6L, new BigDecimal("150.00"));
        map.put(7L, new BigDecimal("150.00"));
        map.put(8L, new BigDecimal("150.00"));
        map.put(9L, new BigDecimal("150.00"));
        map.put(10L, new BigDecimal("150.00"));
        map.put(11L, new BigDecimal("150.00"));
        // ... 可以继续添加元素
        // 使用Stream API按照BigDecimal从大到小排序,并获取前十个元素
        List<Map.Entry<Long, BigDecimal>> topTenEntries = map.entrySet().stream()
                .sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
                .limit(10)
                .collect(Collectors.toList());
        // 打印结果
        for (Map.Entry<Long, BigDecimal> entry : topTenEntries) {
            System.out.println("Key: " + entry.getKey() + ", Value: " + entry.getValue());
        }
    }
}
src/main/java/cc/mrbird/febs/rabbit/QueueConstants.java
@@ -5,19 +5,10 @@
 * @date 2022-05-31
 **/
public class QueueConstants {
    //发送推荐规则奖励
    public static final String TFC_NODE_AGAIN_LONG = "queue_tfc_node_again_long";
    //发送推荐规则奖励
    public static final String TFC_NODE_AGAIN = "queue_tfc_node_again";
    //发送推荐规则奖励
    public static final String TFC_NODE_PERK_QUEEN = "queue_tfc_node_perk";
    //发送推荐规则奖励
    public static final String TFC_INVITE_PERK_QUEEN = "queue_tfc_invite_perk";
    public static final String ONLINE_TRANSFER = "queue_sdm_online_transfer";
    public static final String DISTRIB_PROFIT = "queue_sdm_distrib_profit";
    public static final String USER_BUY_REWARD = "queue_sdm_user_buy_reward";
    public static final String NFT_BOX = "queue_sdm_nft_box";
    public static final String ACHIEVE_TREE = "queue_sdm_achieve_tree";
    public static final String TFC_NEW_PRICE = "queue_tfc_new_price";
    public static final String FPD_MEMBER_LEVEL = "queue_fpd_member_level";
    public static final String FPD_TEAM_PERK = "queue_fpd_team_perk";
    public static final String FPD_NODE_JILI_BUCHANG_PERK = "queue_fpd_node_jili_buchang_perk";
    public static final String FPD_MEMBER_DIRECT_PERK = "queue_fpd_member_direct_perk";
    public static final String FPD_MEMBER_DYNAMIC_PERK = "queue_fpd_member_dynamic_perk";
}
src/main/java/cc/mrbird/febs/rabbit/QueueEnum.java
@@ -5,23 +5,15 @@
@Getter
public enum QueueEnum {
    //发送推荐规则奖励
    TFC_NODE_AGAIN_LONG("exchange_tfc_node_again_long", "route_key_tfc_node_again_long", QueueConstants.TFC_NODE_AGAIN_LONG),
    //发送推荐规则奖励
    TFC_NODE_AGAIN("exchange_tfc_node_again", "route_key_tfc_node_again", QueueConstants.TFC_NODE_AGAIN),
    //发送推荐规则奖励
    TFC_NODE_PERK("exchange_tfc_node_perk", "route_key_tfc_node_perk", QueueConstants.TFC_NODE_PERK_QUEEN),
    //发送推荐规则奖励
    TFC_INVITE_PERK("exchange_tfc_invite_perk", "route_key_tfc_invite_perk", QueueConstants.TFC_INVITE_PERK_QUEEN),
    FPD_MEMBER_LEVEL("exchange_fpd_member_level", "route_key_fpd_member_level", QueueConstants.FPD_MEMBER_LEVEL),
    ONLINE_TRANSFER("exchange_sdm_online_transfer", "route_key_sdm_online_transfer", "queue_sdm_online_transfer"),
    DISTRIB_PROFIT("exchange_sdm_distrib_profit", "route_key_sdm_distrib_profit", "queue_sdm_distrib_profit"),
    USER_BUY_REWARD("exchange_sdm_user_buy_reward", "route_key_sdm_user_buy_reward", "queue_sdm_user_buy_reward"),
    NFT_BOX("exchange_sdm_nft_box", "route_key_sdm_nft_box", "queue_sdm_nft_box"),
    ACHIEVE_TREE("exchange_sdm_achieve_tree", "route_key_sdm_achieve_tree", QueueConstants.ACHIEVE_TREE),
//    ACHIEVE_TREE("exchange_sdm_achieve_tree", "route_key_sdm_achieve_tree", "queue_sdm_achieve_tree"),
    WITHDRAW_FEE("exchange_withdraw_fee", "route_key_withdraw_fee", "queue_withdraw_fee"),
    TFC_NEW_PRICE("exchange_tfc_new_price", "route_key_tfc_new_price", "queue_tfc_new_price");
    FPD_TEAM_PERK("exchange_fpd_team_perk", "route_key_fpd_team_perk", QueueConstants.FPD_TEAM_PERK),
    FPD_NODE_JILI_BUCHANG_PERK("exchange_fpd_node_jili_buchang_perk", "route_key_fpd_node_jili_buchang_perk", QueueConstants.FPD_NODE_JILI_BUCHANG_PERK),
    FPD_MEMBER_DIRECT_PERK("exchange_fpd_member_direct_perk", "route_key_fpd_member_direct_perk", QueueConstants.FPD_MEMBER_DIRECT_PERK),
    FPD_MEMBER_DYNAMIC_PERK("exchange_fpd_member_dynamic_perk", "route_key_fpd_member_dynamic_perk", QueueConstants.FPD_MEMBER_DYNAMIC_PERK);
    private String exchange;
src/main/java/cc/mrbird/febs/rabbit/RabbitConfiguration.java
@@ -29,154 +29,78 @@
        return new RabbitTemplate(connectionFactory);
    }
    // === 业绩树 start ===
    // ===  start ===
    @Bean
    public DirectExchange achieveTreeExchange() {
        return new DirectExchange(QueueEnum.ACHIEVE_TREE.getExchange());
    public DirectExchange memberDynamicExchange() {
        return new DirectExchange(QueueEnum.FPD_MEMBER_DYNAMIC_PERK.getExchange());
    }
    @Bean
    public Queue achieveTreeQueue() {
        return new Queue(QueueEnum.ACHIEVE_TREE.getQueue());
    public Queue memberDynamicQueue() {
        return new Queue(QueueEnum.FPD_MEMBER_DYNAMIC_PERK.getQueue());
    }
    @Bean
    public Binding achieveTreeBind() {
        return BindingBuilder.bind(achieveTreeQueue()).to(achieveTreeExchange()).with(QueueEnum.ACHIEVE_TREE.getRoute());
    public Binding memberDynamicBind() {
        return BindingBuilder.bind(memberDynamicQueue()).to(memberDynamicExchange()).with(QueueEnum.FPD_MEMBER_DYNAMIC_PERK.getRoute());
    }
    // === 业绩树 end ===
    // ===  end ===
    // === 提现手续费 start ===
    // ===  start ===
    @Bean
    public DirectExchange withdrawFeeExchange() {
        return new DirectExchange(QueueEnum.WITHDRAW_FEE.getExchange());
    public DirectExchange memberDirectExchange() {
        return new DirectExchange(QueueEnum.FPD_MEMBER_DIRECT_PERK.getExchange());
    }
    @Bean
    public Queue withdrawFeeQueue() {
        return new Queue(QueueEnum.WITHDRAW_FEE.getQueue());
    public Queue memberDirectQueue() {
        return new Queue(QueueEnum.FPD_MEMBER_DIRECT_PERK.getQueue());
    }
    @Bean
    public Binding withdrawFeeBind() {
        return BindingBuilder.bind(withdrawFeeQueue()).to(withdrawFeeExchange()).with(QueueEnum.WITHDRAW_FEE.getRoute());
    public Binding memberDirectBind() {
        return BindingBuilder.bind(memberDirectQueue()).to(memberDirectExchange()).with(QueueEnum.FPD_MEMBER_DIRECT_PERK.getRoute());
    }
    // === 提现手续费 end ===
    // ===  end ===
    // === tfc最新价 start ===
    // ===  start ===
    @Bean
    public DirectExchange tfcNewPriceExchange() {
        return new DirectExchange(QueueEnum.TFC_NEW_PRICE.getExchange());
    public DirectExchange nodeJiliBuchangExchange() {
        return new DirectExchange(QueueEnum.FPD_NODE_JILI_BUCHANG_PERK.getExchange());
    }
    @Bean
    public Queue tfcNewPriceQueue() {
        return new Queue(QueueEnum.TFC_NEW_PRICE.getQueue());
    public Queue nodeJiliBuchangQueue() {
        return new Queue(QueueEnum.FPD_NODE_JILI_BUCHANG_PERK.getQueue());
    }
    @Bean
    public Binding tfcNewPriceBind() {
        return BindingBuilder.bind(tfcNewPriceQueue()).to(tfcNewPriceExchange()).with(QueueEnum.TFC_NEW_PRICE.getRoute());
    public Binding nodeJiliBuchangBind() {
        return BindingBuilder.bind(nodeJiliBuchangQueue()).to(nodeJiliBuchangExchange()).with(QueueEnum.FPD_NODE_JILI_BUCHANG_PERK.getRoute());
    }
    // === tfc最新价 end ===
    // ===  end ===
    // === 手续费分发 start ===
    // ===  start ===
    @Bean
    public DirectExchange feeDistributeExchange() {
        return new DirectExchange(QueueEnum.DISTRIB_PROFIT.getExchange());
    public DirectExchange teamPerkExchange() {
        return new DirectExchange(QueueEnum.FPD_TEAM_PERK.getExchange());
    }
    @Bean
    public Queue feeDistributeQueue() {
        return new Queue(QueueEnum.DISTRIB_PROFIT.getQueue());
    public Queue teamPerkQueue() {
        return new Queue(QueueEnum.FPD_TEAM_PERK.getQueue());
    }
    @Bean
    public Binding feeDistributeBind() {
        return BindingBuilder.bind(feeDistributeQueue()).to(feeDistributeExchange()).with(QueueEnum.DISTRIB_PROFIT.getRoute());
    public Binding teamPerkBind() {
        return BindingBuilder.bind(teamPerkQueue()).to(teamPerkExchange()).with(QueueEnum.FPD_TEAM_PERK.getRoute());
    }
    // === 手续费分发 end ===
    // ===  end ===
    // === 发送推荐规则奖励 start ===
    // ===  start ===
    @Bean
    public DirectExchange invitePerkExchange() {
        return new DirectExchange(QueueEnum.TFC_INVITE_PERK.getExchange());
    public DirectExchange memberLevelExchange() {
        return new DirectExchange(QueueEnum.FPD_MEMBER_LEVEL.getExchange());
    }
    @Bean
    public Queue invitePerkQueue() {
        return new Queue(QueueEnum.TFC_INVITE_PERK.getQueue());
    public Queue memberLevelQueue() {
        return new Queue(QueueEnum.FPD_MEMBER_LEVEL.getQueue());
    }
    @Bean
    public Binding invitePerkBind() {
        return BindingBuilder.bind(invitePerkQueue()).to(invitePerkExchange()).with(QueueEnum.TFC_INVITE_PERK.getRoute());
    public Binding memberLevelBind() {
        return BindingBuilder.bind(memberLevelQueue()).to(memberLevelExchange()).with(QueueEnum.FPD_MEMBER_LEVEL.getRoute());
    }
    // === 发送推荐规则奖励 end ===
    // === 发送节点奖励 start ===
    @Bean
    public DirectExchange nodePerkExchange() {
        return new DirectExchange(QueueEnum.TFC_NODE_PERK.getExchange());
    }
    @Bean
    public Queue nodePerkQueue() {
        return new Queue(QueueEnum.TFC_NODE_PERK.getQueue());
    }
    @Bean
    public Binding nodePerkBind() {
        return BindingBuilder.bind(nodePerkQueue()).to(nodePerkExchange()).with(QueueEnum.TFC_NODE_PERK.getRoute());
    }
    // === 发送节点奖励 end ===
    // === 发送复投 start ===
    @Bean
    public DirectExchange nodeAgainExchange() {
        return new DirectExchange(QueueEnum.TFC_NODE_AGAIN.getExchange());
    }
    @Bean
    public Queue nodeAgainQueue() {
        return new Queue(QueueEnum.TFC_NODE_AGAIN.getQueue());
    }
    @Bean
    public Binding nodeAgainBind() {
        return BindingBuilder.bind(nodeAgainQueue()).to(nodeAgainExchange()).with(QueueEnum.TFC_NODE_AGAIN.getRoute());
    }
    // === 发送复投 end ===
    // === 发送复投 start ===
    @Bean
    public DirectExchange nodeAgainExchangeLong() {
        return new DirectExchange(QueueEnum.TFC_NODE_AGAIN_LONG.getExchange());
    }
    @Bean
    public Queue nodeAgainQueueLong() {
        return new Queue(QueueEnum.TFC_NODE_AGAIN_LONG.getQueue());
    }
    @Bean
    public Binding nodeAgainBindLong() {
        return BindingBuilder.bind(nodeAgainQueueLong()).to(nodeAgainExchangeLong()).with(QueueEnum.TFC_NODE_AGAIN_LONG.getRoute());
    }
    // === 发送复投 end ===
    // ===  end ===
}
src/main/java/cc/mrbird/febs/rabbit/consumer/ChainConsumer.java
@@ -1,19 +1,13 @@
package cc.mrbird.febs.rabbit.consumer;
import cc.mrbird.febs.dapp.entity.DbMemberNode;
import cc.mrbird.febs.dapp.mapper.DbMemberNodeMapper;
import cc.mrbird.febs.dapp.service.DappSystemService;
import cc.mrbird.febs.rabbit.QueueConstants;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
import org.springframework.stereotype.Component;
import java.util.List;
import javax.annotation.Resource;
/**
 * @author wzy
@@ -21,93 +15,84 @@
 **/
@Slf4j
@Component
@ConditionalOnProperty(prefix = "system", name = "online-transfer", havingValue = "true")
@ConditionalOnProperty(prefix = "system", name = "charge-transfer", havingValue = "true")
public class ChainConsumer {
    @Autowired
    @Resource
    private DappSystemService dappSystemService;
    @Autowired
    private DbMemberNodeMapper dbMemberNodeMapper;
    @RabbitListener(queues = QueueConstants.ACHIEVE_TREE)
    public void achieveTree(String id) {
        log.info("收到业绩树消息");
        dappSystemService.achieveTree(Long.parseLong(id));
    }
    /**
     * 生产者在tfc应用
     * @param data
     * 一、DAO成员静态:
     *  质押PEOPLE(500枚起)静态每天1%。
     *  直推8%
     * 六、永动补偿池2%
     * 五、DAO永动激励池:6%
     * 四、DAO联盟委员会 :   5%  (50名全球DAO委员)
     * @param id 流水ID
     */
    @RabbitListener(queues = QueueConstants.TFC_NEW_PRICE)
    public void tfcNewPrice(String data) {
//        dappSystemService.tfcNewPrice(data);
    @RabbitListener(queues = QueueConstants.FPD_MEMBER_DIRECT_PERK)
    public void directPerkMsg(Long id) {
        log.info("消费直推,流水ID:{}", id);
        dappSystemService.directPerkMsg(id);
    }
    /**
     * @param data
     * 二、DAO成员动态:
     * 1.直推1个拿2代,直推10个拿20代,直推15个拿30代,最高30代
     * 2.   1-5代奖励7%
     *      6-10代奖励6%
     *      11-15代奖励5%
     *      15-20代奖励4%
     *      21-25代奖励4%
     *      26-30代奖励7%
     * @param id 流水ID
     */
    @RabbitListener(queues = QueueConstants.DISTRIB_PROFIT)
    public void feeDistribute(String data) {
        dappSystemService.feeDistribute(data);
    }
    @RabbitListener(queues = QueueConstants.TFC_INVITE_PERK_QUEEN)
    public void invitePerkMsg(Long id) {
        log.info("消费推荐规则奖励,流水ID:{}", id);
    @RabbitListener(queues = QueueConstants.FPD_MEMBER_DYNAMIC_PERK)
    public void memberDynamicPerkMsg(Long id) {
        log.info("消费DAO成员动态,流水ID:{}", id);
        dappSystemService.invitePerkMsg(id);
    }
    @RabbitListener(queues = QueueConstants.TFC_NODE_PERK_QUEEN)
    /**
     * 六、永动补偿池2%
     * 五、DAO永动激励池:6%
     * 四、DAO联盟委员会 :   5%  (50名全球DAO委员)
     * @param id 流水ID
     */
    @RabbitListener(queues = QueueConstants.FPD_NODE_JILI_BUCHANG_PERK)
    public void nodePerkMsg(Long id) {
        log.info("消费节点投资,流水ID:{}", id);
        log.info("消费DAO节点,激励,补偿,流水ID:{}", id);
        dappSystemService.nodePerkMsg(id);
    }
    @RabbitListener(queues = QueueConstants.TFC_NODE_AGAIN)
    public void nodeMsg(Long id) {
        log.info("复投:{}", id);
        dappSystemService.achieveTreeV2(id);
    /**
     *
     *   3.  DAO成员团队奖:5%加权分红(people数量)
     *       DAO1:小区业绩30万/币  加权分红50%
     *       DAO2:小区业绩100万/币 加权分红30%
     *       DAO3:小区业绩500万/币加权分红20%
     */
    @RabbitListener(queues = QueueConstants.FPD_TEAM_PERK)
    public void teamPerk(Long id) {
        log.info("消费成员团队奖5%,流水ID:{}", id);
        dappSystemService.teamPerk(id);
    }
    @RabbitListener(queues = QueueConstants.TFC_NODE_AGAIN_LONG)
    public void nodeMsgLong(Long id) {
        log.info("复投:{}", id);
        /**
         * 获取所有左右节点都有值,轮数为 1,未复投work_state = 1 的节点
         *      判断右节点有值
         *          有继续向判断右节点
         *              有,原纪录复投逻辑
     *
     *   3.  成员升级或者降级
     *       DAO1:小区业绩30万/币
     *       DAO2:小区业绩100万/币
     *       DAO3:小区业绩500万/币
         */
        QueryWrapper<DbMemberNode> objectQueryWrapper = new QueryWrapper<>();
        objectQueryWrapper.eq("count_fund", 1);
        objectQueryWrapper.eq("work_state", 1);
        objectQueryWrapper.eq("type", 1);
        objectQueryWrapper.eq("member_id", id);
        List<DbMemberNode> dbMemberNodes = dbMemberNodeMapper.selectList(objectQueryWrapper);
        if(CollUtil.isEmpty(dbMemberNodes)){
            return;
        }
        for(DbMemberNode dbMemberNode : dbMemberNodes){
            if(ObjectUtil.isEmpty(dbMemberNode.getRightNode())){
                continue;
            }
            //子节点
            Long rightNode = dbMemberNode.getRightNode();
            DbMemberNode dbMemberNode1 = dbMemberNodeMapper.selectById(rightNode);
            if(ObjectUtil.isEmpty(dbMemberNode1)){
                continue;
    @RabbitListener(queues = QueueConstants.FPD_MEMBER_LEVEL)
    public void MemberLevel(Long id) {
        log.info("消费发送成员升级,会员ID:{}", id);
        dappSystemService.MemberLevel(id);
            }
            if(ObjectUtil.isEmpty(dbMemberNode1.getRightNode())){
                continue;
            }
            //有,则上级节点出局复投,轮数加1,复投逻辑
            dappSystemService.memberNodeNext(dbMemberNode);
        }
    }
}
src/main/java/cc/mrbird/febs/rabbit/producer/ChainProducer.java
@@ -33,57 +33,71 @@
    }
    public void sendAchieveTreeMsg(Long id) {
        log.info("发送业绩树消息:{}", id);
        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
        rabbitTemplate.convertAndSend(QueueEnum.ACHIEVE_TREE.getExchange(), QueueEnum.ACHIEVE_TREE.getRoute(), id, correlationData);
    }
    /**
     * 消费者在tfc应用
     *
     * @param data
     */
    public void sendTfcFee(String data) {
        log.info("发送提现手续费消息:{}", data);
        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
        rabbitTemplate.convertAndSend(QueueEnum.WITHDRAW_FEE.getExchange(), QueueEnum.WITHDRAW_FEE.getRoute(), data, correlationData);
    }
    /**
     * 发送手续费分发消息
     *
     * @param id
     */
    public void sendFeeDistributeMsg(Long id) {
        log.info("发送手续费分发消息:{}", id);
        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
        rabbitTemplate.convertAndSend(QueueEnum.DISTRIB_PROFIT.getExchange(), QueueEnum.DISTRIB_PROFIT.getRoute(), id, correlationData);
    }
    /**
     * 推荐规则:
     * 无直推奖励,推2个3层,3个6层,4个10层。1%见点奖(有效层级内,每个每1%),共10层,共%10。
     * 一、DAO成员静态:
     *  质押PEOPLE(500枚起)静态每天1%。
     *  直推8%
     * @param id 流水ID
     */
    public void sendInvitePerkMsg(Long id) {
        log.info("发送推荐规则奖励,流水ID:{}", id);
    public void sendDirectPerkMsg(Long id) {
        log.info("发送直推:{}", id);
        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
        rabbitTemplate.convertAndSend(QueueEnum.TFC_INVITE_PERK.getExchange(), QueueEnum.TFC_INVITE_PERK.getRoute(), id, correlationData);
        rabbitTemplate.convertAndSend(QueueEnum.FPD_MEMBER_DIRECT_PERK.getExchange(), QueueEnum.FPD_MEMBER_DIRECT_PERK.getRoute(), id, correlationData);
    }
    /**
     * 二、DAO成员动态:
     * 1.直推1个拿2代,直推10个拿20代,直推15个拿30代,最高30代
     * 2.   1-5代奖励7%
     *      6-10代奖励6%
     *      11-15代奖励5%
     *      15-20代奖励4%
     *      21-25代奖励4%
     *      26-30代奖励7%
     * @param id 流水ID
     */
    public void sendMemberDynamicPerkMsg(Long id) {
        log.info("发送DAO成员动态,流水ID:{}", id);
        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
        rabbitTemplate.convertAndSend(QueueEnum.FPD_MEMBER_DYNAMIC_PERK.getExchange(), QueueEnum.FPD_MEMBER_DYNAMIC_PERK.getRoute(), id, correlationData);
    }
    /**
     * 六、永动补偿池2%
     * 五、DAO永动激励池:6%
     * 四、DAO联盟委员会 :   5%  (50名全球DAO委员)
     * @param id 流水ID
     */
    public void sendNodePerkMsg(Long id) {
        log.info("发送节点投资,流水ID:{}", id);
        log.info("发送DAO节点,激励,补偿,流水ID:{}", id);
        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
        rabbitTemplate.convertAndSend(QueueEnum.TFC_NODE_PERK.getExchange(), QueueEnum.TFC_NODE_PERK.getRoute(), id, correlationData);
        rabbitTemplate.convertAndSend(QueueEnum.FPD_NODE_JILI_BUCHANG_PERK.getExchange(), QueueEnum.FPD_NODE_JILI_BUCHANG_PERK.getRoute(), id, correlationData);
    }
    public void sendNodeMsg(Long id) {
        log.info("发送复投:{}", id);
    /**
     *
     *   3.  DAO成员团队奖:5%加权分红(people数量)
     *       DAO1:小区业绩30万/币  加权分红50%
     *       DAO2:小区业绩100万/币 加权分红30%
     *       DAO3:小区业绩500万/币加权分红20%
     */
    public void sendTeamPerk(Long id) {
        log.info("发送成员团队奖5%,流水ID:{}", id);
        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
        rabbitTemplate.convertAndSend(QueueEnum.TFC_NODE_AGAIN.getExchange(), QueueEnum.TFC_NODE_AGAIN.getRoute(), id, correlationData);
        rabbitTemplate.convertAndSend(QueueEnum.FPD_TEAM_PERK.getExchange(), QueueEnum.FPD_TEAM_PERK.getRoute(), id, correlationData);
    }
    public void sendNodeMsgLong(Long id) {
        log.info("发送复投原本数据:{}", id);
    /**
     *
     *   3.  成员升级
     *       DAO1:小区业绩30万/币  加权分红50%
     *       DAO2:小区业绩100万/币 加权分红30%
     *       DAO3:小区业绩500万/币加权分红20%
     */
    public void sendMemberLevel(Long id) {
        log.info("发送成员升级,会员ID:{}", id);
        CorrelationData correlationData = new CorrelationData(UUID.randomUUID().toString());
        rabbitTemplate.convertAndSend(QueueEnum.TFC_NODE_AGAIN_LONG.getExchange(), QueueEnum.TFC_NODE_AGAIN_LONG.getRoute(), id, correlationData);
        rabbitTemplate.convertAndSend(QueueEnum.FPD_TEAM_PERK.getExchange(), QueueEnum.FPD_TEAM_PERK.getRoute(), id, correlationData);
    }
}
src/main/resources/application-chain.yml
@@ -54,9 +54,5 @@
    time-zone: GMT+8
system:
  charge-transfer: false
  online-transfer: true
  chain-listener: true
  reset-job: true
  quartz-job: true
  charge-transfer: true
  debug: false
src/main/resources/application-charge.yml
File was deleted
src/main/resources/application-dev.yml
@@ -32,7 +32,7 @@
    # Redis服务器连接端口
    port: 6479
    # Redis 密码
    password: xcong123
    password: d3y6dsdl;f.327
    lettuce:
      pool:
        # 连接池中的最小空闲连接
@@ -58,9 +58,5 @@
    publisher-confirm-type: correlated
system:
  charge-transfer: false
  online-transfer: false
  chain-listener: false
  reset-job: false
  quartz-job: false
  charge-transfer: true
  debug: false
src/main/resources/application-prod.yml
@@ -55,8 +55,4 @@
system:
  charge-transfer: false
  online-transfer: false
  chain-listener: false
  reset-job: false
  quartz-job: false
  debug: false
src/main/resources/application.yml
@@ -1,5 +1,5 @@
server:
  port: 8081
  port: 8082
  tomcat:
    uri-encoding: utf-8
src/main/resources/mapper/dapp/DappFundFlowDao.xml
@@ -4,7 +4,6 @@
    <select id="selectInPage" resultType="cc.mrbird.febs.dapp.entity.DappFundFlowEntity">
        select a.*,
                (a.amount + a.fee) AS amountReal,
               b.address address
        from dapp_fund_flow a
        inner join dapp_member b on a.member_id=b.id
src/main/resources/mapper/dapp/DappStorageMapper.xml
New file
@@ -0,0 +1,53 @@
<?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="cc.mrbird.febs.dapp.mapper.DappStorageMapper">
    <select id="selectOneByDateDesc" resultType="cc.mrbird.febs.dapp.entity.DappStorage">
        select
               *
        from
            dapp_storage
        where
            date_format(create_time, '%Y-%m-%d') = date_format(#{date}, '%Y-%m-%d')
        order by create_time desc
        limit 1
    </select>
    <select id="selectListByDateDesc" resultType="cc.mrbird.febs.dapp.entity.DappStorage">
        select
               *
        from
            dapp_storage
        where
            date_format(create_time, '%Y-%m-%d') = date_format(#{date}, '%Y-%m-%d')
        order by create_time desc
        limit 1,99
    </select>
    <select id="selectListByDate" resultType="cc.mrbird.febs.dapp.entity.DappStorage">
        select
               *
        from
            dapp_storage
        where
            date_format(create_time, '%Y-%m-%d') = date_format(#{date}, '%Y-%m-%d')
        order by create_time desc
    </select>
    <select id="selectAmountByDesc" resultType="cc.mrbird.febs.dapp.entity.DappStorage">
        select
            *
        from
            dapp_storage
        where
                date_format(create_time, '%Y-%m-%d') = date_format(#{date}, '%Y-%m-%d')
        order by amount desc
            limit {offset},{count}
    </select>
</mapper>
src/test/java/cc/mrbird/febs/TreeTest.java
@@ -87,9 +87,9 @@
        fromMember.setActiveStatus(1);
        dappMemberDao.updateById(fromMember);
        chainProducer.sendNodeMsg(fundFlow.getId());
//        chainProducer.sendNodeMsg(fundFlow.getId());
        //发送推荐规则奖励
        chainProducer.sendInvitePerkMsg(fundFlow.getId());
//        chainProducer.sendInvitePerkMsg(fundFlow.getId());
        //发送节点投资
        chainProducer.sendNodePerkMsg(fundFlow.getId());