20221220
1、会员注册后level为会员
2、代理每天一点更新一次定时器
3、确认收货后返还订单金额,并且产生其余补贴
2 files added
19 files modified
702 ■■■■■ changed files
src/main/java/cc/mrbird/febs/common/enumerates/DataDictionaryEnum.java 31 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/common/enumerates/MallMoneyFlowTypeEnum.java 22 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/common/enumerates/MemberAgentLevelEnum.java 102 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/common/enumerates/MoneyFlowTypeEnum.java 11 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/entity/MallMoneyFlow.java 6 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/entity/MallOrderInfo.java 2 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/mapper/MallMemberMapper.java 10 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/mapper/MallMoneyFlowMapper.java 6 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/quartz/OrderOvertimeJob.java 95 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/service/IAgentService.java 6 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/service/IMallMoneyFlowService.java 2 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/service/impl/AgentServiceImpl.java 252 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallMemberServiceImpl.java 2 ●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallOrderInfoServiceImpl.java 75 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/service/impl/MallMoneyFlowServiceImpl.java 17 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/rabbit/constants/QueueConstants.java 1 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/rabbit/consumer/AgentConsumer.java 10 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/rabbit/enumerates/RabbitQueueEnum.java 2 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/rabbit/producter/AgentProducer.java 9 ●●●●● patch | view | raw | blame | history
src/main/resources/mapper/modules/MallMemberMapper.xml 31 ●●●●● patch | view | raw | blame | history
src/main/resources/mapper/modules/MallMoneyFlowMapper.xml 10 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/common/enumerates/DataDictionaryEnum.java
@@ -6,8 +6,39 @@
@Getter
public enum DataDictionaryEnum {
    /**
     * 代理等级
     *  value : {"levelSelf":"一星","directLevelCnt":"3","teamLevelCnt":"5","minTeamLevelCnt":"2","ManageSubsidyPercent":"2"}
     *  levelSelf:自身星级
     *  directLevelCnt:直推星级数量
     *  teamLevelCnt:团队星级数量
     *  minTeamLevelCnt:两个市场均有上一个代理等级
     *  ManageSubsidyPercent:团队管理补贴百分比例,基数为订单补贴金额
     *  subsidyPercent:平级团队管理补贴百分比例,基数为订单补贴金额
     */
    //{"levelSelf":"一星","directLevelCnt":"3","teamLevelCnt":"5","minTeamLevelCnt":"0","manageSubsidyPercent":"2","subsidyPercent":"0"}
    AGENT_ONE("MEMBER_AGENT_LEVEL", "AGENT_ONE"),//区代
    //{"levelSelf":"二星","directLevelCnt":"5","teamLevelCnt":"50","minTeamLevelCnt":"2","manageSubsidyPercent":"4","subsidyPercent":"1"}
    AGENT_TWO("MEMBER_AGENT_LEVEL", "AGENT_TWO"),//县代
    //{"levelSelf":"二星","directLevelCnt":"10","teamLevelCnt":"300","minTeamLevelCnt":"2","manageSubsidyPercent":"7","subsidyPercent":"1"}
    AGENT_THREE("MEMBER_AGENT_LEVEL", "AGENT_THREE"),//市代
    //{"levelSelf":"三星","directLevelCnt":"10","teamLevelCnt":"1000","minTeamLevelCnt":"2","manageSubsidyPercent":"12","subsidyPercent":"1"}
    AGENT_FOUR("MEMBER_AGENT_LEVEL", "AGENT_FOUR"),//省代
    //{"levelSelf":"三星","directLevelCnt":"10","teamLevelCnt":"5000","minTeamLevelCnt":"2","manageSubsidyPercent":"20","subsidyPercent":"1"}
    AGENT_FIVE("MEMBER_AGENT_LEVEL", "AGENT_FIVE"),//总代
    //第一代分享奖比例
    LEVEL_ONE("SHARE_PERCENT", "LEVEL_ONE"),
    //第二代分享奖比例
    LEVEL_TWO("SHARE_PERCENT", "LEVEL_TWO"),
    //直推返利的比例
    REWARD_PERCENT("DIRECT_REWARD", "REWARD_PERCENT"),
    //会员每日可用订单数
    BUY_TIMES("ORDER_BUY", "BUY_TIMES"),
    //商品补贴比例
    SUBSIDY_PERCENT("GOODS_SUBSIDY", "SUBSIDY_PERCENT"),
src/main/java/cc/mrbird/febs/common/enumerates/MallMoneyFlowTypeEnum.java
New file
@@ -0,0 +1,22 @@
package cc.mrbird.febs.common.enumerates;
import lombok.Getter;
@Getter
public enum MallMoneyFlowTypeEnum {
    TEAM_REWARD("团队管理补贴",6),
    PAY("支付",5),
    SHARE_REWARD_TWO("第二代分享奖励",4),
    SHARE_REWARD_ONE("第一代分享奖励",3),
    DIRECT_REWARD("直推奖励",2),
    MARKET_SUBSIDIES("市场补贴",1);
    private String name;
    private Integer code;
    MallMoneyFlowTypeEnum(String name,Integer code) {
        this.name = name;
        this.code = code;
    }
}
src/main/java/cc/mrbird/febs/common/enumerates/MemberAgentLevelEnum.java
New file
@@ -0,0 +1,102 @@
package cc.mrbird.febs.common.enumerates;
import lombok.Getter;
@Getter
public enum MemberAgentLevelEnum {
    AGENT_FIVE("总代","AGENT_FIVE",5),//总代
    AGENT_FOUR("省代","AGENT_FOUR",4),//省代
    AGENT_THREE("市代","AGENT_THREE",3),//市代
    AGENT_TWO("县代","AGENT_TWO",2),//县代
    AGENT_ONE("区代","AGENT_ONE",1),//区代
    AGENT("会员","AGENT",0);//会员
    private String name;
    private String code;
    private Integer value;
    MemberAgentLevelEnum(String name,String code,Integer value) {
        this.name = name;
        this.code = code;
        this.value = value;
    }
    /**
     *
     根据传入的name,比较两个级别的大小
        levelOne等于levelTwo返回2,levelOne大于levelTwo返回1,否则返回0
     */
    public int compareLevel(String levelOne ,String levelTwo) {
        int codeOne = 0;
        int codeTwo = 0;
        for (MemberAgentLevelEnum memberAgentLevelEnum : MemberAgentLevelEnum.values()) {
            if(memberAgentLevelEnum.name.equals(levelOne)){
                codeOne = memberAgentLevelEnum.value;
            }
            if(memberAgentLevelEnum.name.equals(levelTwo)){
                codeTwo = memberAgentLevelEnum.value;
            }
        }
        if(codeOne > codeTwo){
            return 1;
        }
        if(codeOne == codeTwo){
            return 2;
        }
        return 0;
    }
    /**
     * 根据传入的等级code,输出上一等级name
     * @param code
     * @return
     */
    public String minLevel(String code) {
        String minLevel = null;
        for (MemberAgentLevelEnum memberAgentLevelEnum : MemberAgentLevelEnum.values()) {
            if(memberAgentLevelEnum.getCode().equals(code)){
                minLevel = getNameByValue(memberAgentLevelEnum.getValue() - 1);
            }
        }
        return minLevel;
    }
    private String getNameByValue(Integer value){
        String name = null;
        for (MemberAgentLevelEnum memberAgentLevelEnum : MemberAgentLevelEnum.values()) {
            if(memberAgentLevelEnum.getValue() == value){
                name = memberAgentLevelEnum.getName();
            }
        }
        return name;
    }
    /**
     * 根据传入的等级code,输出等级name
     * @param code
     * @return
     */
    public String getNameByCode(String code){
        String name = null;
        for (MemberAgentLevelEnum memberAgentLevelEnum : MemberAgentLevelEnum.values()) {
            if(memberAgentLevelEnum.getCode() == code){
                name = memberAgentLevelEnum.getName();
            }
        }
        return name;
    }
    /**
     * 根据传入的等级name,输出等级code
     * @param name
     * @return
     */
    public String getCodeByName(String name){
        String code = null;
        for (MemberAgentLevelEnum memberAgentLevelEnum : MemberAgentLevelEnum.values()) {
            if(memberAgentLevelEnum.getName() == name){
                code = memberAgentLevelEnum.getCode();
            }
        }
        return code;
    }
}
src/main/java/cc/mrbird/febs/common/enumerates/MoneyFlowTypeEnum.java
@@ -2,18 +2,13 @@
import lombok.Getter;
/**
 *
 * 1-静态收益 2-直推奖 3-代理收益 4-排名收益 5-总监收益 6-社区点补 7-一代收益 8-提现 9-转增 10-支付 11-退款
 * @author wzy
 * @date 2021-09-24
 **/
@Getter
public enum MoneyFlowTypeEnum {
    /**
     * 静态收益
     * 市场补贴
     */
    STATIC_BONUS(1),
    MARKET_DUBSIDIES(1),
    STATIC_BONUS(100),
    /**
     * 直推奖
     */
src/main/java/cc/mrbird/febs/mall/entity/MallMoneyFlow.java
@@ -32,15 +32,19 @@
    private Long rtMemberId;
    /**
     * 提现状态 1-提现中2-成功 3-拒绝
     * 提现状态 1-进行中2-成功 3-拒绝
     */
    private Integer status;
    public static final Integer STATUS_ING = 1;
    public static final Integer STATUS_SUCCESS = 2;
    public static final Integer STATUS_FAIL = 3;
    /**
     * 是否返利 1-是 2-否
     */
    private Integer isReturn;
    public static final Integer IS_RETURN_Y = 1;
    public static final Integer IS_RETURN_N = 2;
    /**
     * 流水类型 1-余额 2-赠送积分 3-竞猜积分 4-佣金
src/main/java/cc/mrbird/febs/mall/entity/MallOrderInfo.java
@@ -93,4 +93,6 @@
    private Integer deliverType;
    private Long shopId;
    //补贴金额
    private BigDecimal subsidyAmount;
}
src/main/java/cc/mrbird/febs/mall/mapper/MallMemberMapper.java
@@ -85,4 +85,14 @@
    List<MallMember> selectDirectorsOrStoreMaster(@Param("type") Integer type);
    List<MallMember> selectMemberWithLevel(String level);
    List<MallMember> selectByAccountLevel(@Param("accountLevel")String accountLevel);
    Integer selectByRefererIdAndAccountLevel(@Param("refererId")String refererId,@Param("accountLevel") String accountLevel);
    Integer selectByReferersIdAndAccountLevel(@Param("inviteId")String inviteId,@Param("accountLevel") String accountLevel);
    void updateLevelById(@Param("level")String name, @Param("id")Long id);
    Integer selectByReferersIdAndLevel(@Param("inviteId")String inviteId, @Param("level")String minLevel);
}
src/main/java/cc/mrbird/febs/mall/mapper/MallMoneyFlowMapper.java
@@ -37,4 +37,10 @@
    BigDecimal selectCommissionIncome(@Param("type") Integer type, @Param("date") Date date, @Param("memberId") Long memebrid);
    BigDecimal selectThankfulCommission(@Param("date") Date date, @Param("memberId") Long memberId);
    MallMoneyFlow selectOneByMemberIdAndOrderNoAndTypeAndStatusAndIsReturn(@Param("memberId")Long memberId,
                                                                           @Param("orderNo")String orderNo,
                                                                           @Param("type")Integer type,
                                                                           @Param("status")Integer status,
                                                                           @Param("isReturn")Integer isReturn);
}
src/main/java/cc/mrbird/febs/mall/quartz/OrderOvertimeJob.java
@@ -1,11 +1,20 @@
package cc.mrbird.febs.mall.quartz;
import cc.mrbird.febs.common.enumerates.DataDictionaryEnum;
import cc.mrbird.febs.common.enumerates.MemberAccountLevelEnum;
import cc.mrbird.febs.common.enumerates.MemberAgentLevelEnum;
import cc.mrbird.febs.common.enumerates.OrderStatusEnum;
import cc.mrbird.febs.mall.entity.DataDictionaryCustom;
import cc.mrbird.febs.mall.entity.MallMember;
import cc.mrbird.febs.mall.entity.MallOrderInfo;
import cc.mrbird.febs.mall.mapper.DataDictionaryCustomMapper;
import cc.mrbird.febs.mall.mapper.MallMemberMapper;
import cc.mrbird.febs.mall.mapper.MallOrderInfoMapper;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUnit;
import cn.hutool.core.date.DateUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
@@ -25,6 +34,12 @@
    @Autowired
    private MallOrderInfoMapper orderInfoMapper;
    @Autowired
    private MallMemberMapper mallMemberMapper;
    @Autowired
    private DataDictionaryCustomMapper dataDictionaryCustomMapper;
    @Scheduled(cron = "0 0/5 * * * ? ")
    public void overtimeJob() {
        log.info("订单超时任务执行");
@@ -42,4 +57,84 @@
        }
    }
    @Scheduled(cron = "0 0 1 * * ? ")
    public void updateMemberAgentLevel() {
        log.info("会员代理等级升级任务执行");
        /**
         * 获取会员信息
         *  1、已经升级成为一星
         */
        /**
         * 区代
         *  1、自身一星
         *  2、直推三个星级
         *  3、团队五个星级
         */
        updateMemberAgentLevelByName(DataDictionaryEnum.AGENT_ONE.getType(),DataDictionaryEnum.AGENT_ONE.getCode());
        /**
         * 县代
         *  1、自身2星
         *  2、直推5个星级
         *  3、团队50个星级
         */
        updateMemberAgentLevelByName(DataDictionaryEnum.AGENT_TWO.getType(),DataDictionaryEnum.AGENT_TWO.getCode());
        updateMemberAgentLevelByName(DataDictionaryEnum.AGENT_THREE.getType(),DataDictionaryEnum.AGENT_THREE.getCode());
        updateMemberAgentLevelByName(DataDictionaryEnum.AGENT_FOUR.getType(),DataDictionaryEnum.AGENT_FOUR.getCode());
        updateMemberAgentLevelByName(DataDictionaryEnum.AGENT_FIVE.getType(),DataDictionaryEnum.AGENT_FIVE.getCode());
    }
    private void updateMemberAgentLevelByName(String name,String code){
        DataDictionaryCustom agentDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
                name,
                code
        );
        JSONObject jsonObject = JSONUtil.parseObj(agentDic.getValue());
        //自身星级
        String levelSelf = jsonObject.get("levelSelf").toString();
        //直推星级数量
        String directLevelCnt = jsonObject.get("directLevelCnt").toString();
        //团队星级数量
        String teamLevelCnt = jsonObject.get("teamLevelCnt").toString();
        //两个市场均有上一个代理等级
        String minTeamLevelCnt = jsonObject.get("minTeamLevelCnt").toString();
        List<MallMember> agentLevelList = mallMemberMapper.selectByAccountLevel(levelSelf);
        if(CollUtil.isNotEmpty(agentLevelList)){
            for(MallMember mallMember : agentLevelList){
                //有星级的直推
                Integer directCnt = mallMemberMapper.selectByRefererIdAndAccountLevel(mallMember.getInviteId(),MemberAccountLevelEnum.NORMAL.getName());
                //团队中星级会员数量
                Integer teamCnt = mallMemberMapper.selectByReferersIdAndAccountLevel(mallMember.getInviteId(),MemberAccountLevelEnum.NORMAL.getName());
                //两个市场均有上一个代理等级
                Integer minCnt = 0;
                if(0 < Integer.parseInt(minTeamLevelCnt)){
                    String minLevel = MemberAgentLevelEnum.AGENT_ONE.minLevel(code);
                    //获取所有直推用户
                    List<MallMember> mallMembers = mallMemberMapper.selectByRefererId(mallMember.getInviteId());
                    if(CollUtil.isNotEmpty(mallMembers) && mallMembers.size() > 2){
                        Integer levelCnt = 0;
                        for(MallMember directMember : mallMembers){
                            Integer minlevelCnt = mallMemberMapper.selectByReferersIdAndLevel(directMember.getInviteId(),minLevel);
                            if(0 < minlevelCnt){
                                levelCnt = levelCnt + 1;
                            }
                            if(levelCnt >= Integer.parseInt(minTeamLevelCnt)){
                                minCnt = 1;
                                break;
                            }
                        }
                    }
                }else{
                    //区代不需要判断这个市场条件
                    minCnt = 1;
                }
                if(Integer.parseInt(directLevelCnt) <= directCnt
                        && Integer.parseInt(teamLevelCnt) <= teamCnt
                        && minCnt > 0){
                    //更新会员代理等级
                    mallMemberMapper.updateLevelById(MemberAgentLevelEnum.AGENT_ONE.getNameByCode(code),mallMember.getId());
                }
            }
        }
    }
}
src/main/java/cc/mrbird/febs/mall/service/IAgentService.java
@@ -7,4 +7,10 @@
    void returnMoneyToAgent(Long orderId);
    void rankReturnMoney(Long orderId);
    /**
     * 消费补贴奖励、直推返利、分享奖励直推上级、分享奖励直推上级的直推、团队管理补贴消息
     * @param directRewardId
     */
    void directReward(Long directRewardId);
}
src/main/java/cc/mrbird/febs/mall/service/IMallMoneyFlowService.java
@@ -15,4 +15,6 @@
    void addMoneyFlow(Long memberId, BigDecimal amount, Integer type, String orderNo, Long rtMemberId, Integer flowType);
    Long addMoneyFlow(Long memberId, String orderNo,BigDecimal amount, Integer type, Integer status, Integer isReturn,Long rtMemberId, Integer flowType,String description);
}
src/main/java/cc/mrbird/febs/mall/service/impl/AgentServiceImpl.java
@@ -1,19 +1,14 @@
package cc.mrbird.febs.mall.service.impl;
import cc.mrbird.febs.common.enumerates.AgentLevelEnum;
import cc.mrbird.febs.common.enumerates.MoneyFlowTypeEnum;
import cc.mrbird.febs.common.enumerates.*;
import cc.mrbird.febs.common.utils.AppContants;
import cc.mrbird.febs.mall.entity.AgentInfo;
import cc.mrbird.febs.mall.entity.DataDictionaryCustom;
import cc.mrbird.febs.mall.entity.MallMember;
import cc.mrbird.febs.mall.entity.MallOrderInfo;
import cc.mrbird.febs.mall.entity.*;
import cc.mrbird.febs.mall.mapper.*;
import cc.mrbird.febs.mall.service.IAgentService;
import cc.mrbird.febs.mall.service.IApiMallMemberService;
import cc.mrbird.febs.mall.service.IApiMallMemberWalletService;
import cc.mrbird.febs.mall.service.IMallAchieveService;
import cc.mrbird.febs.mall.service.*;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import jdk.nashorn.internal.ir.IfNode;
import lombok.RequiredArgsConstructor;
@@ -39,6 +34,9 @@
    private final DataDictionaryCustomMapper dataDictionaryCustomMapper;
    private final MallMemberMapper memberMapper;
    private final MallOrderInfoMapper mallOrderInfoMapper;
    private final IMallMoneyFlowService mallMoneyFlowService;
    private final IApiMallMemberWalletService memberWalletService;
    @Override
    @Transactional(rollbackFor = Exception.class)
@@ -136,7 +134,6 @@
    /**
     * 团队业绩是否达标
     *
     * @param mallMember
     * @param agentInfo
     * @return
     */
@@ -161,4 +158,237 @@
    public void rankReturnMoney(Long orderId) {
    }
    @Override
    public void directReward(Long directRewardId) {
        log.info("消费补贴奖励、直推返利、分享奖励直推上级、分享奖励直推上级的直推、团队管理补贴消息,ID:{}", directRewardId);
        //获取订单信息
        MallOrderInfo orderInfo = mallOrderInfoMapper.selectById(directRewardId);
        if(ObjectUtil.isEmpty(orderInfo)){
            return;
        }
        Integer status = orderInfo.getStatus();
        if(OrderStatusEnum.FINISH.getValue() != status){
            return;
        }
        //下单补贴金额
        BigDecimal subsidyAmount = orderInfo.getSubsidyAmount();
        //下单人
        Long memberId = orderInfo.getMemberId();
        MallMember mallMember = memberMapper.selectById(memberId);
        /**
         * 生成补贴的流水记录
         *  1、待生效
         *  2、返利对象,下单人
         *  3、金额,补贴金额
         */
        Long subsidyAmountFlowId = mallMoneyFlowService.addMoneyFlow(
                mallMember.getId(),
                orderInfo.getOrderNo(),
                subsidyAmount.setScale(BigDecimal.ROUND_DOWN, 2),
                MallMoneyFlowTypeEnum.MARKET_SUBSIDIES.getCode(),
                MallMoneyFlow.STATUS_SUCCESS,
                MallMoneyFlow.IS_RETURN_Y,
                mallMember.getId(),
                FlowTypeEnum.BALANCE.getValue(),
                MallMoneyFlowTypeEnum.MARKET_SUBSIDIES.getName()
        );
        memberWalletService.addBalance(subsidyAmount.setScale(BigDecimal.ROUND_DOWN, 2),mallMember.getId());
        /**
         * 生成直推返利的流水记录
         *  1、待生效
         *  2、返利对象:下单人的直推上级
         *  3、金额:返利比例乘以补贴金额
         */
        //下单人的直推上级
        MallMember mallMemberOne = memberMapper.selectInfoByInviteId(mallMember.getReferrerId());
        DataDictionaryCustom rewardPercentDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
                DataDictionaryEnum.REWARD_PERCENT.getType(),
                DataDictionaryEnum.REWARD_PERCENT.getCode()
        );
        BigDecimal rewardPercent = new BigDecimal(rewardPercentDic.getValue()).multiply(new BigDecimal(0.01)).setScale(BigDecimal.ROUND_DOWN,2);
        BigDecimal directRewardAmount = subsidyAmount.multiply(rewardPercent).setScale(BigDecimal.ROUND_DOWN, 2);
        Long marketSubsidyFlowId = mallMoneyFlowService.addMoneyFlow(
                mallMember.getId(),
                orderInfo.getOrderNo(),
                directRewardAmount,
                MallMoneyFlowTypeEnum.DIRECT_REWARD.getCode(),
                MallMoneyFlow.STATUS_SUCCESS,
                MallMoneyFlow.IS_RETURN_Y,
                mallMemberOne.getId(),
                FlowTypeEnum.BALANCE.getValue(),
                MallMoneyFlowTypeEnum.DIRECT_REWARD.getName()
        );
        memberWalletService.addBalance(directRewardAmount,mallMemberOne.getId());
        /**
         * 生成分享奖励的流水记录
         *  1、待生效
         *  2、返利对象:下单人的直推上级 10%,直推的直推 5%
         *  3、金额:补贴金额乘以分享奖励的比例
         */
        DataDictionaryCustom shareOneDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
                DataDictionaryEnum.LEVEL_ONE.getType(),
                DataDictionaryEnum.LEVEL_ONE.getCode()
        );
        BigDecimal shareOne = new BigDecimal(shareOneDic.getValue()).multiply(new BigDecimal(0.01)).setScale(BigDecimal.ROUND_DOWN,2);
        BigDecimal shareOneAmount = subsidyAmount.multiply(shareOne).setScale(BigDecimal.ROUND_DOWN, 2);
        Long ShareOneFlowId = mallMoneyFlowService.addMoneyFlow(
                mallMember.getId(),
                orderInfo.getOrderNo(),
                shareOneAmount,
                MallMoneyFlowTypeEnum.SHARE_REWARD_ONE.getCode(),
                MallMoneyFlow.STATUS_SUCCESS,
                MallMoneyFlow.IS_RETURN_Y,
                mallMemberOne.getId(),
                FlowTypeEnum.BALANCE.getValue(),
                MallMoneyFlowTypeEnum.SHARE_REWARD_ONE.getName()
        );
        memberWalletService.addBalance(shareOneAmount,mallMemberOne.getId());
        //下单人的直推上级的直推
        MallMember mallMemberTwo = memberMapper.selectInfoByInviteId(mallMemberOne.getReferrerId());
        if(ObjectUtil.isNotEmpty(mallMemberTwo)){
            DataDictionaryCustom shareTwoDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
                    DataDictionaryEnum.LEVEL_TWO.getType(),
                    DataDictionaryEnum.LEVEL_TWO.getCode()
            );
            BigDecimal shareTwo = new BigDecimal(shareTwoDic.getValue()).multiply(new BigDecimal(0.01)).setScale(BigDecimal.ROUND_DOWN,2);
            BigDecimal shareTwoAmount = subsidyAmount.multiply(shareTwo).setScale(BigDecimal.ROUND_DOWN, 2);
            Long shareTwoFlowId = mallMoneyFlowService.addMoneyFlow(
                    mallMember.getId(),
                    orderInfo.getOrderNo(),
                    shareTwoAmount,
                    MallMoneyFlowTypeEnum.SHARE_REWARD_TWO.getCode(),
                    MallMoneyFlow.STATUS_SUCCESS,
                    MallMoneyFlow.IS_RETURN_Y,
                    mallMemberTwo.getId(),
                    FlowTypeEnum.BALANCE.getValue(),
                    MallMoneyFlowTypeEnum.SHARE_REWARD_TWO.getName()
            );
            memberWalletService.addBalance(shareTwoAmount,mallMemberTwo.getId());
        }
        /**
         * 团队管理补贴
         */
        //下单人所有的上级
        String referrerIds = mallMember.getReferrerIds();
        List<String> refererIdList = StrUtil.split(referrerIds, ",", -1, true, true);
        //下单人所有符合条件的上级-邀请码
        ArrayList<String> refererIdListUp = new ArrayList<>();
        //初始级别即当前下单人的级别
        String levelStart = mallMember.getLevel();
        for(String inviteId : refererIdList){
            MallMember mallMemberUp = memberMapper.selectInfoByInviteId(inviteId);
            String levelUp = mallMemberUp.getLevel();
            //团队补贴从区代开始
            if(!MemberAgentLevelEnum.AGENT.getName().equals(levelUp)){
                //比较两个代理级别,同级别或者大于下单人的级别都保留
                int compareLevel = MemberAgentLevelEnum.AGENT_ONE.compareLevel(levelUp,levelStart);
                if(0 < compareLevel){
                    levelStart = levelUp;
                    refererIdListUp.add(inviteId);
                }
            }
        }
        if(CollUtil.isNotEmpty(refererIdListUp)){
            for(String inviteId : refererIdList){
                MallMember mallMemberUp = memberMapper.selectInfoByInviteId(inviteId);
                String levelUp = mallMemberUp.getLevel();
                //获取团队分享比例
                BigDecimal manageSubsidyPercent = getManageSubsidyPercent(levelStart, levelUp);
                if(manageSubsidyPercent.compareTo(BigDecimal.ZERO) > 0){
                    BigDecimal teamManageAmount = subsidyAmount.multiply(manageSubsidyPercent).setScale(BigDecimal.ROUND_DOWN, 2);
                    //生成团队分享流水
                    Long teamManageFlowId = mallMoneyFlowService.addMoneyFlow(
                            mallMember.getId(),
                            orderInfo.getOrderNo(),
                            teamManageAmount,
                            MallMoneyFlowTypeEnum.SHARE_REWARD_TWO.getCode(),
                            MallMoneyFlow.STATUS_SUCCESS,
                            MallMoneyFlow.IS_RETURN_Y,
                            mallMemberUp.getId(),
                            FlowTypeEnum.BALANCE.getValue(),
                            MallMoneyFlowTypeEnum.TEAM_REWARD.getName()
                    );
                    memberWalletService.addBalance(teamManageAmount,mallMemberUp.getId());
                }
                levelStart = levelUp;
            }
        }
    }
    /**
     * 根据传入的两个级别,比较之后获取对应的团队管理奖励比例
     * @param levelStart
     * @param levelUp
     * @return
     */
    private BigDecimal getManageSubsidyPercent(String levelStart,String levelUp){
        BigDecimal manageSubsidyPercent = BigDecimal.ZERO;
        String agentCodeStart = MemberAgentLevelEnum.AGENT_ONE.getCodeByName(levelStart);
        String agentCodeUp = MemberAgentLevelEnum.AGENT_ONE.getCodeByName(levelUp);
        int compareLevel = MemberAgentLevelEnum.AGENT_ONE.compareLevel(levelUp, levelStart);
        //如果是平级
        if(compareLevel == 2){
            manageSubsidyPercent = getDicSubsidyPercent(agentCodeStart);
        }
        //如果不是平级
        if(compareLevel == 1){
            //1、初始级别不能是会员
            //2、当前级别的上一个级别是否是levelStart,
            // 满足,需要减去levelStart的团队管理奖励
            String minLevel = MemberAgentLevelEnum.AGENT_ONE.minLevel(agentCodeUp);
            if(levelStart.equals(minLevel)
                    && MemberAgentLevelEnum.AGENT.getName() != levelStart){
                BigDecimal dicManageSubsidyPercentUp = getDicManageSubsidyPercent(agentCodeUp);
                BigDecimal dicManageSubsidyPercentStart = getDicManageSubsidyPercent(agentCodeStart);
                manageSubsidyPercent = dicManageSubsidyPercentUp.subtract(dicManageSubsidyPercentStart);
            }else{
                manageSubsidyPercent = getDicManageSubsidyPercent(agentCodeUp);
            }
        }
        return manageSubsidyPercent;
    }
    /**
     * 获取对应的团队管理奖励比例
     * @param agentCode
     * @return
     */
    private BigDecimal getDicManageSubsidyPercent(String agentCode){
        BigDecimal manageSubsidyPercent = BigDecimal.ZERO;
        DataDictionaryCustom agentDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
                DataDictionaryEnum.AGENT_ONE.getType(),
                agentCode
        );
        cn.hutool.json.JSONObject jsonObject = JSONUtil.parseObj(agentDic.getValue());
        String manageSubsidyPercentStr = jsonObject.get("manageSubsidyPercent").toString();
        manageSubsidyPercent =  new BigDecimal(manageSubsidyPercentStr)
                .multiply(new BigDecimal(0.01))
                .setScale(BigDecimal.ROUND_DOWN,2);
        return manageSubsidyPercent;
    }
    /**
     * 获取对应的平级团队管理奖励比例
     * @param agentCode
     * @return
     */
    private BigDecimal getDicSubsidyPercent(String agentCode){
        BigDecimal subsidyPercent = BigDecimal.ZERO;
        DataDictionaryCustom agentDic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(
                DataDictionaryEnum.AGENT_ONE.getType(),
                agentCode
        );
        cn.hutool.json.JSONObject jsonObject = JSONUtil.parseObj(agentDic.getValue());
        String subsidyPercentStr = jsonObject.get("manageSubsidyPercent").toString();
        subsidyPercent =  new BigDecimal(subsidyPercentStr)
                .multiply(new BigDecimal(0.01))
                .setScale(BigDecimal.ROUND_DOWN,2);
        return subsidyPercent;
    }
}
src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallMemberServiceImpl.java
@@ -112,7 +112,7 @@
        mallMember.setAccountStatus(MallMember.ACCOUNT_STATUS_ENABLE);
        mallMember.setAccountType(MallMember.ACCOUNT_TYPE_NORMAL);
        mallMember.setAccountLevel(MemberAccountLevelEnum.NORMAL.getName());
        mallMember.setLevel(AgentLevelEnum.ZERO_LEVEL.name());
        mallMember.setLevel(MemberAgentLevelEnum.AGENT.getName());
        mallMember.setSex("男");
        mallMember.setBindPhone(registerDto.getAccount());
src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallOrderInfoServiceImpl.java
@@ -69,6 +69,7 @@
    private final MallShoppingCartMapper mallShoppingCartMapper;
    private final IApiMallMemberService memberService;
    private final IMallMoneyFlowService mallMoneyFlowService;
    private final MallMoneyFlowMapper mallMoneyFlowMapper;
    private final RedisUtils redisUtils;
    private final AgentProducer agentProducer;
@@ -131,7 +132,8 @@
//        orderInfo.setLongitude(address.getLongitude());
        orderInfo.setRemark(addOrderDto.getRemark());
        orderInfo.setOrderType(addOrderDto.getOrderType());
        //补贴金额
        orderInfo.setSubsidyAmount(goods.getSubsidyAmount());
        if (CollUtil.isEmpty(addOrderDto.getItems())) {
            throw new FebsException("参数错误");
        }
@@ -361,46 +363,22 @@
                orderInfo.setPayTime(new Date());
                orderInfo.setPayResult("1");
//                boolean hasTc = false;
                // 静态倍数
//                List<MallOrderItem> orderItems = this.baseMapper.getMallOrderItemByOrderId(orderInfo.getId());
//                if (CollUtil.isNotEmpty(orderItems)) {
//                    for (MallOrderItem orderItem : orderItems) {
//                        MallGoods mallGoods = mallGoodsMapper.selectById(orderItem.getGoodsId());
//                        BigDecimal score = BigDecimal.ZERO;
//                        MallGoodsSku sku = mallGoodsSkuMapper.selectById(orderItem.getSkuId());
//                        if (mallGoods.getIsNormal() == 2) {
//                            hasTc = true;
//                            score = sku.getPresentPrice().multiply(mallGoods.getStaticMulti()).multiply(new BigDecimal(orderItem.getCnt()));
////                            BigDecimal staticMulti = mallGoods.getStaticMulti() == null ? BigDecimal.ZERO : mallGoods.getStaticMulti();
////                            score = sku.getPresentPrice().multiply(staticMulti);
//                            // 普通商品也及时结算,不再10天结算
//                        } else {
//                            score = sku.getPresentPrice();
//                        }
//
//                        if (score.compareTo(BigDecimal.ZERO) > 0) {
//                            memberWalletService.add(score, member.getId(), "score");
//                            mallMoneyFlowService.addMoneyFlow(member.getId(), score, MoneyFlowTypeEnum.STATIC_BONUS.getValue(), orderInfo.getOrderNo(), FlowTypeEnum.SCORE.getValue());
//
//                            // 添加业绩
//                            mallAchieveService.add(orderItem.getId());
//                        }
//                    }
//                }
//                mallMoneyFlowService.addMoneyFlow(member.getId(), orderInfo.getAmount().negate(), MoneyFlowTypeEnum.PAY.getValue(), orderInfo.getOrderNo(), FlowTypeEnum.BALANCE.getValue());
                /**
                 * 生成下单的流水记录
                 */
                Long payFlowId = mallMoneyFlowService.addMoneyFlow(
                        member.getId(),
                        orderInfo.getOrderNo(),
                        orderInfo.getAmount().negate().setScale(BigDecimal.ROUND_DOWN, 2),
                        MallMoneyFlowTypeEnum.PAY.getCode(),
                        MallMoneyFlow.STATUS_SUCCESS,
                        MallMoneyFlow.IS_RETURN_N,
                        member.getId(),
                        FlowTypeEnum.BALANCE.getValue(),
                        MallMoneyFlowTypeEnum.PAY.getName()
                );
                // 购买套餐后,升级为普通会员
//                if (hasTc) {
//                    MallMember mallMember = memberMapper.selectById(member.getId());
//                    if (AgentLevelEnum.ZERO_LEVEL.name().equals(mallMember.getLevel())) {
//                        mallMember.setLevel(AgentLevelEnum.FIRST_LEVEL.name());
//                        memberMapper.updateById(mallMember);
//                    }
//                }
                mallMoneyFlowService.addMoneyFlow(member.getId(), orderInfo.getAmount().negate(), MoneyFlowTypeEnum.PAY.getValue(), orderInfo.getOrderNo(), FlowTypeEnum.BALANCE.getValue());
//                agentProducer.sendAutoLevelUpMsg(member.getId());
//                agentProducer.sendOrderReturn(orderInfo.getId());
                break;
            case "4":
                if (orderInfo.getOrderType() != 2) {
@@ -600,6 +578,23 @@
        orderInfo.setStatus(OrderStatusEnum.FINISH.getValue());
        orderInfo.setReceivingTime(new Date());
        this.baseMapper.updateById(orderInfo);
        /**
         * 通过支付流水记录,返回下单金额
         */
        MallMoneyFlow payFlow = mallMoneyFlowMapper.selectOneByMemberIdAndOrderNoAndTypeAndStatusAndIsReturn(
                member.getId(),
                orderInfo.getOrderNo(),
                MallMoneyFlowTypeEnum.PAY.getCode(),
                MallMoneyFlow.STATUS_SUCCESS,
                MallMoneyFlow.IS_RETURN_N);
        if(ObjectUtil.isNotEmpty(payFlow)){
            memberWalletService.addBalance(payFlow.getAmount().negate(),payFlow.getRtMemberId());
            payFlow.setIsReturn(MallMoneyFlow.IS_RETURN_Y);
            mallMoneyFlowMapper.updateById(payFlow);
        }
        //产生补贴流水记录
        agentProducer.sendDirectRewardMsg(orderInfo.getId());
    }
    @Override
src/main/java/cc/mrbird/febs/mall/service/impl/MallMoneyFlowServiceImpl.java
@@ -49,4 +49,21 @@
    public void addMoneyFlow(Long memberId, BigDecimal amount, Integer type, String orderNo, Long rtMemberId, Integer flowType) {
        this.addMoneyFlow(memberId, amount, type, orderNo, null, null, rtMemberId, null, flowType, null);
    }
    @Override
    public Long addMoneyFlow(Long memberId,String orderNo,BigDecimal amount, Integer type, Integer status, Integer isReturn, Long rtMemberId, Integer flowType, String description) {
        MallMoneyFlow flow = new MallMoneyFlow();
        flow.setMemberId(memberId);
        flow.setOrderNo(orderNo);
        flow.setAmount(amount);
        flow.setType(type);
        flow.setStatus(status);
        flow.setIsReturn(isReturn);
        flow.setRtMemberId(rtMemberId);
        flow.setFlowType(flowType);
        flow.setDescription(description);
        this.baseMapper.insert(flow);
        return flow.getId();
    }
}
src/main/java/cc/mrbird/febs/rabbit/constants/QueueConstants.java
@@ -10,4 +10,5 @@
    public static final String AGENT_AUTO_LEVEL_UP = "queue_agent_auto_level_up";
    public static final String AGENT_RETURN_MONEY = "queue_agent_return_money";
    public static final String ORDER_RETURN_MONEY = "queue_order_return_money";
    public static final String MALL_COIN_DIRECT_REWARD = "queue_mall_coin_direct_reward";
}
src/main/java/cc/mrbird/febs/rabbit/consumer/AgentConsumer.java
@@ -72,4 +72,14 @@
            log.error("订单返利异常:", e);
        }
    }
    @RabbitListener(queues = QueueConstants.MALL_COIN_DIRECT_REWARD)
    public void directReward(Long directRewardId) {
        log.info("消费补贴奖励、直推返利、分享奖励直推上级、分享奖励直推上级的直推、团队管理补贴消息:{}", directRewardId);
        try {
            agentService.directReward(directRewardId);
        } catch (Exception e) {
            log.error("消费奖励异常", e);
        }
    }
}
src/main/java/cc/mrbird/febs/rabbit/enumerates/RabbitQueueEnum.java
@@ -4,6 +4,8 @@
@Getter
public enum RabbitQueueEnum {
    //补贴奖励、直推返利、分享奖励直推上级、分享奖励直推上级的直推、团队管理补贴
    MALL_COIN_DIRECT_REWARD("exchange_mall_coin_direct_reward", "route_key_mall_coin_direct_reward", "queue_mall_coin_direct_reward"),
    DEFAULT("exchange_default", "route_key_default", "queue_default"),
src/main/java/cc/mrbird/febs/rabbit/producter/AgentProducer.java
@@ -76,4 +76,13 @@
        log.info("发送返利消息:{}", orderId);
        rabbitTemplate.convertAndSend(RabbitQueueEnum.AGENT_REUTRN_MONEY.getExchange(), RabbitQueueEnum.AGENT_REUTRN_MONEY.getRoute(), orderId);
    }
    /**
     * 发送直推奖励消息
     * @param directRewardId 订单ID
     */
    public void sendDirectRewardMsg(@NotNull Long directRewardId) {
        log.info("发送补贴奖励、直推返利、分享奖励直推上级、分享奖励直推上级的直推、团队管理补贴消息:{}", directRewardId);
        rabbitTemplate.convertAndSend(RabbitQueueEnum.MALL_COIN_DIRECT_REWARD.getExchange(), RabbitQueueEnum.MALL_COIN_DIRECT_REWARD.getRoute(), directRewardId);
    }
}
src/main/resources/mapper/modules/MallMemberMapper.xml
@@ -400,4 +400,35 @@
        select * from mall_member
        where level=#{level}
    </select>
    <select id="selectByAccountLevel" resultType="cc.mrbird.febs.mall.entity.MallMember">
        select * from mall_member
        where account_level = #{accountLevel}
    </select>
    <select id="selectByRefererIdAndAccountLevel" resultType="java.lang.Integer">
        select count(id) from mall_member
        where account_level != #{accountLevel}
        and referer_id = #{refererId}
    </select>
    <select id="selectByReferersIdAndAccountLevel" resultType="java.lang.Integer">
        select count(id) from mall_member
        where account_level != #{accountLevel}
            and FIND_IN_SET(#{inviteId}, referrer_ids)
    </select>
    <update id="updateLevelById">
        update mall_member
        set
            level = #{level}
        where
            id = #{id}
    </update>
    <select id="selectByReferersIdAndLevel" resultType="java.lang.Integer">
        select count(id) from mall_member
        where level = #{level}
          and FIND_IN_SET(#{inviteId}, referrer_ids)
    </select>
</mapper>
src/main/resources/mapper/modules/MallMoneyFlowMapper.xml
@@ -132,4 +132,14 @@
          and date_format(created_time, '%Y-%m-%d') = date_format(#{date}, '%Y-%m-%d')
          and type in (2,3,4)
    </select>
    <select id="selectOneByMemberIdAndOrderNoAndTypeAndStatusAndIsReturn" resultType="cc.mrbird.febs.mall.entity.MallMoneyFlow">
        select a.*
        from mall_money_flow a
        where a.memberId = #{memberId}
            and a.order_no = #{orderNo}
            and a.type = #{type}
            and a.status = #{status}
            and a.is_return = #{isReturn}
    </select>
</mapper>