Helius
2021-09-26 c2a08e408b08e21a7595eaeaaf8483c5df030d24
add agent auto level up
1 files added
16 files modified
281 ■■■■■ changed files
src/main/java/cc/mrbird/febs/common/configure/RabbitConfigure.java 9 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/common/enumerates/AgentLevelEnum.java 26 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/common/utils/AppContants.java 3 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/entity/AgentInfo.java 4 ●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/mapper/DataDictionaryCustomMapper.java 4 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/mapper/MallMemberMapper.java 6 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/mapper/MallOrderInfoMapper.java 2 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/service/IAgentService.java 4 ●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/service/impl/AgentServiceImpl.java 95 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallMemberServiceImpl.java 8 ●●●● 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 9 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/rabbit/producter/AgentProducer.java 11 ●●●●● patch | view | raw | blame | history
src/main/resources/mapper/modules/DataDictionaryCustomMapper.xml 14 ●●●●● patch | view | raw | blame | history
src/main/resources/mapper/modules/MallMemberMapper.xml 19 ●●●●● patch | view | raw | blame | history
src/main/resources/mapper/modules/MallOrderInfoMapper.xml 14 ●●●●● patch | view | raw | blame | history
src/test/java/cc/mrbird/febs/AgentTest.java 52 ●●●●● patch | view | raw | blame | history
src/main/java/cc/mrbird/febs/common/configure/RabbitConfigure.java
@@ -81,5 +81,14 @@
        return BindingBuilder.bind(orderDelayQueueTtl()).to(delayTtlExchange()).with(RabbitQueueEnum.ORDER_CANCEL_DELAY_TTL.getRoute());
    }
    @Bean
    public Queue autoLevelUpAgentQueue() {
        return new Queue(QueueConstants.AGENT_AUTO_LEVEL_UP);
    }
    @Bean
    public Binding autoLevelUpBind() {
        return BindingBuilder.bind(autoLevelUpAgentQueue()).to(defaultExchange()).with(RouteKeyConstants.ROUTE_KEY_DEFAULT);
    }
}
src/main/java/cc/mrbird/febs/common/enumerates/AgentLevelEnum.java
New file
@@ -0,0 +1,26 @@
package cc.mrbird.febs.common.enumerates;
import lombok.Getter;
/**
 * @author wzy
 * @date 2021-09-26
 **/
@Getter
public enum AgentLevelEnum {
    FIRST_LEVEL("普通会员"),
    SECOND_LEVEL("业务经理"),
    THIRD_LEVEL("区域代理"),
    FOUR_LEVEL("代理"),
    FIFTH_LEVEL("总代"),
    SIX_LEVEL("董事"),
    SEVEN_LEVEL("股东");
    private String name;
    AgentLevelEnum(String name) {
        this.name = name;
    }
}
src/main/java/cc/mrbird/febs/common/utils/AppContants.java
@@ -65,4 +65,7 @@
    public static final String REDIS_ORDER_OVERTIME_PREFIX = "order_overtime_";
    public static final String REDIS_ORDER_OVERTIME = "order_overtime_{}_{}";
    public static final String AGENT_LEVEL = "AGENT_LEVEL";
    public static final String AGENT_LEVEL_REQUIRE = "AGENT_LEVEL_REQUIRE";
}
src/main/java/cc/mrbird/febs/mall/entity/AgentInfo.java
@@ -15,6 +15,8 @@
     * 下单数量要求 1-直推 2-团队
     */
    private Integer orderType;
    public static final Integer ORDER_TYPE_DIRECT = 1;
    public static final Integer ORDER_TYPE_TEAM = 2;
    /**
     * 下单数量
@@ -39,6 +41,6 @@
    /**
     * 团队收益 1-指定金额 2-比例
     */
    private BigDecimal teamIncomeType;
    private Integer teamIncomeType;
}
src/main/java/cc/mrbird/febs/mall/mapper/DataDictionaryCustomMapper.java
@@ -18,4 +18,8 @@
    IPage<AdminPayMethodVo> getPayMethodListInPage(Page<AdminPayMethodVo> page, @Param("record")PayMethodDto payMethodDto);
    AdminMallPayMethodEditVo getMallPayMethodEditInfoById(@Param("id")long id);
    DataDictionaryCustom selectNextAgentLevelInfo(@Param("level") String agentLevel);
    DataDictionaryCustom selectDicDataByTypeAndCode(String type, String code);
}
src/main/java/cc/mrbird/febs/mall/mapper/MallMemberMapper.java
@@ -34,4 +34,10 @@
    Integer selectOwnCntByInviteId(@Param("inviteId") String inviteId);
    Integer selectOwnOrderCntByInviteId(@Param("inviteId") String inviteId);
    List<MallMember> selectByRefererId(@Param("inviteId") String inviteId);
    List<MallMember> selectChildAgentList(@Param("inviteId") String inviteId, @Param("agentLevel") String agentLevel);
    List<MallMember> selectByInviteIds(@Param("list") List<String> inviteIds);
}
src/main/java/cc/mrbird/febs/mall/mapper/MallOrderInfoMapper.java
@@ -38,4 +38,6 @@
    List<MallOrderItem> getMallOrderItemByOrderId(@Param("id")long id);
    List<MallOrderInfo> selectOrderInfoByStatus(@Param("status") Integer status);
    Integer selectCntDirectOrTeam(@Param("type") Integer type, @Param("inviteId") String inviteId);
}
src/main/java/cc/mrbird/febs/mall/service/IAgentService.java
@@ -2,7 +2,7 @@
public interface IAgentService {
    void autoUpAgentLevel();
    void autoUpAgentLevel(Long memberId);
    void returnMoneyToAgent();
    void returnMoneyToAgent(Long orderId);
}
src/main/java/cc/mrbird/febs/mall/service/impl/AgentServiceImpl.java
@@ -1,9 +1,21 @@
package cc.mrbird.febs.mall.service.impl;
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.mapper.DataDictionaryCustomMapper;
import cc.mrbird.febs.mall.mapper.MallMemberMapper;
import cc.mrbird.febs.mall.mapper.MallOrderInfoMapper;
import cc.mrbird.febs.mall.service.IAgentService;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSONObject;
import jdk.nashorn.internal.ir.IfNode;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import java.util.List;
/**
 * @author wzy
@@ -14,13 +26,90 @@
@RequiredArgsConstructor
public class AgentServiceImpl implements IAgentService {
    @Override
    public void autoUpAgentLevel() {
    private final DataDictionaryCustomMapper dataDictionaryCustomMapper;
    private final MallMemberMapper memberMapper;
    private final MallOrderInfoMapper orderInfoMapper;
    @Override
    public void autoUpAgentLevel(Long memberId) {
        MallMember member = memberMapper.selectById(memberId);
        if(StrUtil.isBlank(member.getReferrerIds())) {
            return;
        }
        List<String> ids = StrUtil.split(member.getReferrerIds(), ',');
        List<MallMember> parentMembers = memberMapper.selectByInviteIds(ids);
        for (MallMember parent : parentMembers) {
            DataDictionaryCustom nextLevel = dataDictionaryCustomMapper.selectNextAgentLevelInfo(parent.getLevel());
            if (nextLevel == null) {
                log.info("当前层级无下一级:{}", parent.getLevel());
                return;
            }
            AgentInfo agentInfo = JSONObject.parseObject(nextLevel.getValue(), AgentInfo.class);
            if (!orderCntFinish(parent, agentInfo)) {
                return;
            }
            if (!agentCntFinish(parent, agentInfo)) {
                return;
            }
            parent.setLevel(nextLevel.getCode());
            memberMapper.updateById(parent);
        }
    }
    /**
     * 判断用户直推下单数量或团队下单数量是否达标
     *
     * @return
     */
    private boolean orderCntFinish(MallMember member, AgentInfo agentInfo) {
        Integer cnt = orderInfoMapper.selectCntDirectOrTeam(agentInfo.getOrderType(), member.getInviteId());
        if (cnt >= agentInfo.getOrderCnt()) {
            return true;
        }
        log.info("用户{}订单未达标, 当前数量为:{},要求数量:{}, 当前等级为:{}", member.getAccount(), cnt, agentInfo.getOrderCnt(), member.getLevel());
        return false;
    }
    /**
     * 判断下级代理数量是否达标
     *
     * @return
     */
    private boolean agentCntFinish(MallMember member, AgentInfo agentInfo) {
        if (agentInfo.getLastCnt() == null) {
            return true;
        }
        // 直推用户
        List<MallMember> directMember = memberMapper.selectByRefererId(member.getInviteId());
        if (CollUtil.isEmpty(directMember)) {
            return false;
        }
        // 用户团队达到指定代理数量,且都不在同一条线
        int i = 0;
        for (MallMember child : directMember) {
            List<MallMember> mallMembers = memberMapper.selectChildAgentList(child.getInviteId(), member.getLevel());
            if (CollUtil.isNotEmpty(mallMembers)) {
                i++;
            }
        }
        if (i >= agentInfo.getLastCnt()) {
            return true;
        }
        log.info("用户:{}代理数量未达标, 当前等级:{}, 当前数量:{}, 目标数量:{}", member.getAccount(), member.getLevel(), i, agentInfo.getLastCnt());
        return false;
    }
    @Override
    public void returnMoneyToAgent() {
    public void returnMoneyToAgent(Long orderId) {
    }
}
src/main/java/cc/mrbird/febs/mall/service/impl/ApiMallMemberServiceImpl.java
@@ -1,6 +1,7 @@
package cc.mrbird.febs.mall.service.impl;
import cc.mrbird.febs.common.entity.FebsResponse;
import cc.mrbird.febs.common.enumerates.AgentLevelEnum;
import cc.mrbird.febs.common.enumerates.MoneyFlowTypeEnum;
import cc.mrbird.febs.common.exception.FebsException;
import cc.mrbird.febs.common.utils.*;
@@ -53,6 +54,7 @@
    private final MallMoneyFlowMapper mallMoneyFlowMapper;
    private final IApiMallMemberWalletService walletService;
    private final MallMemberPaymentMapper mallMemberPaymentMapper;
    private final DataDictionaryCustomMapper dataDictionaryCustomMapper;
    @Value("${spring.profiles.active}")
    private String active;
@@ -95,7 +97,7 @@
        mallMember.setName(registerDto.getAccount());
        mallMember.setAccountStatus(MallMember.ACCOUNT_STATUS_ENABLE);
        mallMember.setAccountType(MallMember.ACCOUNT_TYPE_NORMAL);
        mallMember.setLevel("1");
        mallMember.setLevel(AgentLevelEnum.FIRST_LEVEL.name());
        mallMember.setSex("男");
        this.baseMapper.insert(mallMember);
@@ -220,6 +222,10 @@
            mallMemberVo.setHasPayment(1);
        }
        DataDictionaryCustom dic = dataDictionaryCustomMapper.selectDicDataByTypeAndCode(AppContants.AGENT_LEVEL, mallMember.getLevel());
        if (dic != null) {
            mallMemberVo.setLevelName(dic.getDescription());
        }
        MallMemberWallet wallet = mallMemberWalletMapper.selectWalletByMemberId(mallMemberVo.getId());
        mallMemberVo.setBalance(wallet.getBalance());
        return new FebsResponse().success().data(mallMemberVo);
src/main/java/cc/mrbird/febs/rabbit/constants/QueueConstants.java
@@ -7,4 +7,5 @@
public class QueueConstants {
    public static final String QUEUE_DEFAULT = "queue_default";
    public static final String AGENT_AUTO_LEVEL_UP = "queue_agent_auto_level_up";
}
src/main/java/cc/mrbird/febs/rabbit/consumer/AgentConsumer.java
@@ -1,5 +1,6 @@
package cc.mrbird.febs.rabbit.consumer;
import cc.mrbird.febs.mall.service.IAgentService;
import cc.mrbird.febs.mall.service.IApiMallOrderInfoService;
import cc.mrbird.febs.rabbit.constants.QueueConstants;
import cc.mrbird.febs.rabbit.enumerates.RabbitQueueEnum;
@@ -22,6 +23,8 @@
    @Autowired
    private IApiMallOrderInfoService orderInfoService;
    @Autowired
    private IAgentService agentService;
    @RabbitListener(queues = QueueConstants.QUEUE_DEFAULT)
    public void agentReturn(Message message, Channel channel) {
@@ -33,4 +36,10 @@
        log.info("订单超时支付自动取消:{}", id);
        orderInfoService.autoCancelOrder(Long.parseLong(id));
    }
    @RabbitListener(queues = QueueConstants.AGENT_AUTO_LEVEL_UP)
    public void agentAutoLevelUp(String id) {
        log.info("收到代理自动升级消息:{}", id);
        agentService.autoUpAgentLevel(Long.parseLong(id));
    }
}
src/main/java/cc/mrbird/febs/rabbit/producter/AgentProducer.java
@@ -12,6 +12,7 @@
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.validation.constraints.NotNull;
import java.util.Date;
import java.util.UUID;
@@ -60,4 +61,14 @@
            }
        });
    }
    /**
     * 发送代理自动升级消息
     *
     * @param memberId
     */
    public void sendAutoLevelUpMsg(@NotNull Long memberId) {
        log.info("发送代理自动升级消息:{}", memberId);
        rabbitTemplate.convertAndSend(ExchangeConstants.EXCHANGE_DEFAULT, RouteKeyConstants.ROUTE_KEY_DEFAULT, memberId);
    }
}
src/main/resources/mapper/modules/DataDictionaryCustomMapper.xml
@@ -14,4 +14,18 @@
        select * from data_dictionary_custom where id = #{id}
    </select>
    <select id="selectNextAgentLevelInfo" resultType="cc.mrbird.febs.mall.entity.DataDictionaryCustom">
        select * from data_dictionary_custom x
        where x.type='AGENT_LEVEL_REQUIRE' and x.code = (
            select a.code from data_dictionary_custom a
            where a.type='AGENT_LEVEL' and a.value > (select b.value from data_dictionary_custom b where b.type='AGENT_LEVEL' and b.code=#{level})
            order by a.value limit 1
        )
    </select>
    <select id="selectDicDataByTypeAndCode" resultType="cc.mrbird.febs.mall.entity.DataDictionaryCustom">
        select * from data_dictionary_custom a
        where a.type=#{type} and a.code=#{code}
    </select>
</mapper>
src/main/resources/mapper/modules/MallMemberMapper.xml
@@ -94,4 +94,23 @@
                 inner join mall_order_info b on e.id=b.member_id and b.status=4
        where e.invite_id=#{inviteId} or e.referrer_id=#{inviteId}
    </select>
    <select id="selectByRefererId" resultType="cc.mrbird.febs.mall.entity.MallMember">
        select * from mall_member
        where referrer_id=#{inviteId}
    </select>
    <select id="selectChildAgentList" resultType="cc.mrbird.febs.mall.entity.MallMember">
        select * from mall_member
        where find_in_set(#{inviteId}, referrer_ids) and level=#{agentLevel}
    </select>
    <select id="selectByInviteIds" resultType="cc.mrbird.febs.mall.entity.MallMember">
        select * from mall_member
        where  invite_id IN
        <foreach collection = "list" item = "item"  separator=","  open = "(" close = ")" >
            #{item}
        </foreach >
        order by id desc
    </select>
</mapper>
src/main/resources/mapper/modules/MallOrderInfoMapper.xml
@@ -142,4 +142,18 @@
    <select id="selectOrderInfoByStatus" resultType="cc.mrbird.febs.mall.entity.MallOrderInfo">
        select * from mall_order_info where status=#{status}
    </select>
    <select id="selectCntDirectOrTeam" resultType="java.lang.Integer">
        select IFNULL(count(1), 0) from mall_order_info a
          inner join mall_member b on a.member_id=b.ID
        <where>
            a.status=4
            <if test="type == 1">
                and b.referrer_id=#{inviteId}
            </if>
            <if test="type == 2">
                and find_in_set(#{inviteId}, b.referrer_ids)
            </if>
        </where>
    </select>
</mapper>
src/test/java/cc/mrbird/febs/AgentTest.java
@@ -1,10 +1,19 @@
package cc.mrbird.febs;
import cc.mrbird.febs.common.enumerates.AgentLevelEnum;
import cc.mrbird.febs.mall.entity.AgentInfo;
import cc.mrbird.febs.mall.entity.DataDictionaryCustom;
import cc.mrbird.febs.mall.mapper.DataDictionaryCustomMapper;
import cc.mrbird.febs.mall.service.IAgentService;
import cc.mrbird.febs.rabbit.producter.AgentProducer;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.weaver.loadtime.Agent;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.math.BigDecimal;
/**
 * @author wzy
@@ -17,8 +26,51 @@
    @Autowired
    private AgentProducer agentProducer;
    @Autowired
    private DataDictionaryCustomMapper dataDictionaryCustomMapper;
    @Autowired
    private IAgentService agentService;
    @Test
    public void agentTest() {
//        agentProducer.sendDelayMsg(1L, 10000L);
    }
    @Test
    public void insertAgentTest() {
        AgentInfo agentInfo = new AgentInfo();
        agentInfo.setOrderType(2);
        agentInfo.setOrderCnt(2000);
        agentInfo.setLastCnt(3);
        agentInfo.setDirectIncome(BigDecimal.valueOf(50));
        agentInfo.setTeamIncome(BigDecimal.valueOf(15));
        agentInfo.setTeamIncomeType(2);
        DataDictionaryCustom data = new DataDictionaryCustom();
        data.setType("AGENT_LEVEL_REQUIRE");
        data.setCode(AgentLevelEnum.FOUR_LEVEL.name());
        data.setValue(JSONObject.toJSONString(agentInfo));
        dataDictionaryCustomMapper.insert(data);
    }
    @Test
    public void insertData() {
        int i = 1;
        for (AgentLevelEnum value : AgentLevelEnum.values()) {
            DataDictionaryCustom data = new DataDictionaryCustom();
            data.setType("AGENT_LEVEL");
            data.setDescription(value.getName());
            data.setCode(value.name());
            data.setValue(String.valueOf(i));
            dataDictionaryCustomMapper.insert(data);
        }
    }
    @Test
    public void autoLevelUp() {
        // agentService.autoUpAgentLevel(3L);
        agentProducer.sendAutoLevelUpMsg(3L);
    }
}