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); } }