Commit 416de628 authored by zhangfeng's avatar zhangfeng

Merge branch 'refs/heads/feature_member_score_zhangfeng' into feature_member_score

parents f0cc8fba 8f8d6430
package cn.iocoder.yudao.module.member.api;
import cn.iocoder.yudao.module.member.enums.ScoreRuleTypeEnum;
/**
* @author zhangfeng
*/
public interface ScoreProducerApi {
void sendOderMessage(ScoreRuleTypeEnum scoreRuleType, Long orderId);
void sendRecommendMessage(ScoreRuleTypeEnum scoreRuleType, Long userId);
void sendRegisterMessage(ScoreRuleTypeEnum scoreRuleType, Long userId);
void sendRecommendMessage(ScoreRuleTypeEnum scoreRuleType, Long userId, String referralCode);
void sendRegisterMessage(ScoreRuleTypeEnum scoreRuleType, Long userId, String userNameZh, String userNameEn, String phone, Integer registerPlatform);
}
package cn.iocoder.yudao.module.member.enums;
import java.util.stream.Stream;
public enum TransportTypeEnum {
OCEAN_LCL(1, "海运拼柜"),
SPECIAL_LINE_AIR_FREIGHT(3, "专线空运");
......@@ -20,4 +22,7 @@ public enum TransportTypeEnum {
public String getName() {
return name;
}
public static TransportTypeEnum parseByValue(int value) {
return Stream.of(values()).filter(e -> e.getValue() == value).findAny().orElse(null);
}
}
......@@ -45,5 +45,7 @@ public class AppAuthRegReqVO {
private String englishName;
@ApiModelProperty(value = "推荐码", required = false)
private String referralCode;
@ApiModelProperty(value = "注册平台(2APP,3WEB)", required = true)
private Integer registerPlatform;
}
......@@ -34,4 +34,7 @@ public class AppAuthSmsLoginReqVO {
@Pattern(regexp = "^[0-9]+$", message = "{app.auth.captcha.pattern}")
private String code;
@ApiModelProperty(value = "登录平台(2APP,3WEB)", required = true, example = "1")
private Integer loginPlatform;
}
......@@ -95,7 +95,14 @@ public class MemberUserDO extends TenantBaseDO {
*/
private String controlPassword;
/**
* 推荐码
*/
private String referralCode;
/**
* 注册平台
*/
private Integer registerPlatform;
///**
// * 是否身份认证
......
package cn.iocoder.yudao.module.member.dal.redis;
/**
* 占位,后续有类后,可以删除,避免 package 无法提交到 Git 上
* Redis Key 枚举类
*/
package cn.iocoder.yudao.module.member.dal.redis;
public interface RedisKeyConstant {
String MEMBER_USER_SCORE_RULE = "member:user:score:rule:";
}
package cn.iocoder.yudao.module.member.dal.redis.scoreRule;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.module.member.dal.dataobject.scoreRule.ScoreRuleDO;
import cn.iocoder.yudao.module.member.dal.redis.RedisKeyConstant;
import cn.iocoder.yudao.module.member.enums.ScoreRuleTypeEnum;
import cn.iocoder.yudao.module.member.enums.TransportTypeEnum;
import cn.iocoder.yudao.module.member.vo.scoreRule.extra.ScoreRuleOrderVExtraVO;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Repository;
import javax.annotation.Resource;
/**
* 会员积分规则 Redis DAO
*/
@Repository
public class ScoreRuleRedisDao {
@Resource
private StringRedisTemplate stringRedisTemplate;
public ScoreRuleDO getEnableScoreRule(ScoreRuleTypeEnum type, TransportTypeEnum transportType) {
// 如果transportType不为空则是订单V值类型
if (transportType == null) {
String redisKey = formatKey(type.getValue(), null);
String scoreRuleJson = stringRedisTemplate.opsForValue().get(redisKey);
if (scoreRuleJson == null) {
return null;
}
return JsonUtils.parseObject(scoreRuleJson, ScoreRuleDO.class);
} else {
String redisKey = formatKey(type.getValue(), transportType.getValue());
String scoreRuleJson = stringRedisTemplate.opsForValue().get(redisKey);
if (scoreRuleJson == null) {
return null;
}
return JsonUtils.parseObject(scoreRuleJson, ScoreRuleDO.class);
}
}
public ScoreRuleDO getEnableScoreRule(ScoreRuleTypeEnum type) {
return getEnableScoreRule(type, null);
}
public void setEnableScoreRule(ScoreRuleDO scoreRuleDO) {
// 多余字段置空
scoreRuleDO.setCreator(null);
scoreRuleDO.setUpdater(null);
scoreRuleDO.setUpdateTime(null);
scoreRuleDO.setCreateTime(null);
scoreRuleDO.setDeleted(null);
scoreRuleDO.setCoverImageEn(null);
scoreRuleDO.setCoverImageZh(null);
scoreRuleDO.setDescEn(null);
scoreRuleDO.setDescZh(null);
if (scoreRuleDO.getType() == ScoreRuleTypeEnum.ORDER_V.getValue()) {
ScoreRuleOrderVExtraVO scoreRuleOrderVExtraVO = JsonUtils.parseObject(scoreRuleDO.getExtra(), ScoreRuleOrderVExtraVO.class);
stringRedisTemplate.opsForValue().set(formatKey(scoreRuleDO.getType(), scoreRuleOrderVExtraVO.getTransportType()), JsonUtils.toJsonString(scoreRuleDO));
}
stringRedisTemplate.opsForValue().set(formatKey(scoreRuleDO.getType(), null), JsonUtils.toJsonString(scoreRuleDO));
}
public void deleteEnableScoreRule(Integer type) {
if (ScoreRuleTypeEnum.ORDER_V.getValue() == type) {
stringRedisTemplate.delete(formatKey(type, 1));
stringRedisTemplate.delete(formatKey(type, 3));
}
String redisKey = formatKey(type, null);
stringRedisTemplate.delete(redisKey);
}
private static String formatKey(Integer type, Integer transportType) {
if (transportType == null) {
return RedisKeyConstant.MEMBER_USER_SCORE_RULE + type;
}
return RedisKeyConstant.MEMBER_USER_SCORE_RULE + type + ":" + transportType;
}
}
package cn.iocoder.yudao.module.member.mq.consumer.score.core;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQuery;
import cn.iocoder.yudao.module.member.dal.dataobject.scoreRule.ScoreRuleDO;
import cn.iocoder.yudao.module.member.enums.ScoreRuleStatusEnum;
import cn.iocoder.yudao.module.member.enums.ScoreRuleTypeEnum;
import cn.iocoder.yudao.module.member.enums.TransportTypeEnum;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.module.member.dal.dataobject.scoreLog.MemberUserScoreLogDO;
import cn.iocoder.yudao.module.member.service.scoreLog.MemberUserScoreLogService;
import cn.iocoder.yudao.module.member.service.scoreRule.ScoreRuleService;
import cn.iocoder.yudao.module.member.service.user.MemberUserService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import java.util.Date;
import java.util.List;
/**
* 半成品
* @author zhangfeng
*/
public abstract class AbstractScoreRuleStrategy implements ScoreRuleStrategy {
private static ScoreRuleDO orderVShipScoreRule = null;
private static ScoreRuleDO orderVFlyScoreRule = null;
private static ScoreRuleDO registerScoreRule = null;
private static ScoreRuleDO recommendScoreRule = null;
protected ScoreRuleService scoreRuleService;
protected MemberUserScoreLogService memberUserScoreLogService;
protected MemberUserService memberUserService;
@Autowired
public AbstractScoreRuleStrategy(ScoreRuleService scoreRuleService) {
public AbstractScoreRuleStrategy(ScoreRuleService scoreRuleService, MemberUserScoreLogService memberUserScoreLogService,MemberUserService memberUserService) {
this.scoreRuleService = scoreRuleService;
this.memberUserScoreLogService = memberUserScoreLogService;
this.memberUserService = memberUserService;
}
public ScoreRuleDO getEnableScoreRuleByType(ScoreRuleTypeEnum scoreRuleType) {
ScoreRuleDO scoreRuleDO = scoreRuleService.selectOne(new LambdaQuery<ScoreRuleDO>()
.eq(ScoreRuleDO::getType, scoreRuleType.getValue())
.eq(ScoreRuleDO::getStatus, ScoreRuleStatusEnum.ENABLED.getValue()));
if (scoreRuleDO != null) {
// 校验一下活动开始结束时间
if (!scoreRuleDO.getEndTime().after(new Date()) || !scoreRuleDO.getStartTime().before(new Date())) {
return null;
} else {
recommendScoreRule = scoreRuleDO;
return recommendScoreRule;
/**
* 计算用户在某一活动获得积分总数
* @param scoreRuleId
* @param userId
* @return
*/
protected Integer getUserScoreTotalCount(Long scoreRuleId, Long userId) {
Integer userScoreTotalCount = 0;
LambdaQueryWrapper<MemberUserScoreLogDO> scoreLogQueryWrapper = new LambdaQueryWrapper<>();
scoreLogQueryWrapper.eq(MemberUserScoreLogDO::getMemberId, userId)
.eq(MemberUserScoreLogDO::getRuleId, scoreRuleId);
List<MemberUserScoreLogDO> memberUserScoreLogs = memberUserScoreLogService.selectList(scoreLogQueryWrapper);
if (CollUtil.isNotEmpty(memberUserScoreLogs)) {
for (MemberUserScoreLogDO memberUserScoreLog : memberUserScoreLogs) {
userScoreTotalCount += memberUserScoreLog.getScoreCount();
}
}
return null;
}
public ScoreRuleDO getEnableScoreRuleByType(ScoreRuleTypeEnum scoreRuleType, TransportTypeEnum transportType) {
ScoreRuleDO scoreRuleDO = null;
switch (scoreRuleType) {
case ORDER_V:
scoreRuleDO = scoreRuleService.getEnabledOrderVScoreRuleByTransportType(transportType.getValue());
if (scoreRuleDO != null) {
if (!scoreRuleDO.getEndTime().after(new Date()) || !scoreRuleDO.getStartTime().before(new Date())) {
return null;
}
if (transportType == TransportTypeEnum.OCEAN_LCL) {
orderVShipScoreRule = scoreRuleDO;
return orderVShipScoreRule;
}
if (transportType == TransportTypeEnum.SPECIAL_LINE_AIR_FREIGHT) {
orderVFlyScoreRule = scoreRuleDO;
return orderVFlyScoreRule;
}
}
break;
case RECOMMEND:
case REGISTER:
return getEnableScoreRuleByType(scoreRuleType);
}
return null;
}
@Override
public void refreshScoreRule(ScoreRuleTypeEnum scoreRuleType) {
switch (scoreRuleType) {
case ORDER_V:
orderVShipScoreRule = null;
orderVFlyScoreRule = null;
break;
case RECOMMEND:
recommendScoreRule = null;
break;
case REGISTER:
registerScoreRule = null;
break;
}
return userScoreTotalCount;
}
}
package cn.iocoder.yudao.module.member.mq.consumer.score.core;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.json.JSONUtil;
......@@ -12,14 +11,13 @@ import cn.iocoder.yudao.module.customer.dal.dataobject.customerContacts.Customer
import cn.iocoder.yudao.module.customer.service.customerContacts.CustomerContactsService;
import cn.iocoder.yudao.module.member.api.score.MemberUserScoreApi;
import cn.iocoder.yudao.module.member.api.score.dto.MemberUserScoreOperateReqDTO;
import cn.iocoder.yudao.module.member.dal.dataobject.scoreLog.MemberUserScoreLogDO;
import cn.iocoder.yudao.module.member.dal.dataobject.scoreRule.ScoreRuleDO;
import cn.iocoder.yudao.module.member.enums.*;
import cn.iocoder.yudao.module.member.mq.message.ScoreMessage;
import cn.iocoder.yudao.module.member.service.scoreLog.MemberUserScoreLogService;
import cn.iocoder.yudao.module.member.service.scoreRule.ScoreRuleService;
import cn.iocoder.yudao.module.member.service.user.MemberUserService;
import cn.iocoder.yudao.module.member.vo.scoreRule.extra.ScoreRuleOrderVExtraVO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
......@@ -27,7 +25,6 @@ import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Objects;
......@@ -37,18 +34,16 @@ import java.util.Objects;
*/
@Service
@Slf4j
public class OderVStrategy extends AbstractScoreRuleStrategy {
public class OrderVStrategy extends AbstractScoreRuleStrategy {
@Resource
private OrderApi orderApi;
@Resource
private MemberUserScoreApi memberUserScoreApi;
@Resource
private MemberUserScoreLogService memberUserScoreLogService;
@Resource
private CustomerContactsService customerContactsService;
public OderVStrategy(ScoreRuleService scoreRuleService) {
super(scoreRuleService);
public OrderVStrategy(ScoreRuleService scoreRuleService, MemberUserScoreLogService memberUserScoreLogService, MemberUserService memberUserService) {
super(scoreRuleService, memberUserScoreLogService, memberUserService);
}
@Override
......@@ -72,16 +67,11 @@ public class OderVStrategy extends AbstractScoreRuleStrategy {
}
// 判断海运空运
Integer transportId = order.getTransportId();
ScoreRuleDO scoreRuleDO = scoreRuleService.getEnabledOrderVScoreRuleByTransportType(transportId);
ScoreRuleDO scoreRuleDO = scoreRuleService.getEnableScoreRuleByType(ScoreRuleTypeEnum.ORDER_V, TransportTypeEnum.parseByValue(transportId));
if (Objects.isNull(scoreRuleDO)) {
log.info("Order in shipping listener: No score rule match,orderID:{}", orderId);
return;
}
// 是否过期,或者活动还没开始
if (!scoreRuleDO.getEndTime().after(new Date()) || !scoreRuleDO.getStartTime().before(new Date())) {
log.info("Order in shipping listener: The score rule has expired,scoreRuleID:{}", scoreRuleDO.getId());
return;
}
// 目的地信息
OrderObjectiveApiDO orderObjectiveDO = order.getOrderObjectiveDO();
ScoreRuleOrderVExtraVO extraInfo = JSONUtil.toBean(scoreRuleDO.getExtra(), ScoreRuleOrderVExtraVO.class);
......@@ -156,16 +146,7 @@ public class OderVStrategy extends AbstractScoreRuleStrategy {
}
}
// 校验累计最高分
Integer userScoreTotalCount = 0;
LambdaQueryWrapper<MemberUserScoreLogDO> scoreLogQueryWrapper = new LambdaQueryWrapper<>();
scoreLogQueryWrapper.eq(MemberUserScoreLogDO::getMemberId, userId)
.eq(MemberUserScoreLogDO::getRuleId, scoreRuleDO.getId());
List<MemberUserScoreLogDO> memberUserScoreLogs = memberUserScoreLogService.selectList(scoreLogQueryWrapper);
if (CollUtil.isNotEmpty(memberUserScoreLogs)) {
for (MemberUserScoreLogDO memberUserScoreLog : memberUserScoreLogs) {
userScoreTotalCount += memberUserScoreLog.getScoreCount();
}
}
Integer userScoreTotalCount = getUserScoreTotalCount(scoreRuleDO.getId(), userId);
if (userScoreTotalCount >= scoreRuleDO.getMaxScoreTotal()) {
log.info("Order in shipping listener: The user has reached the maximum score,userId:{},scoreRuleId:{}", userId, scoreRuleDO.getId());
return;
......@@ -177,7 +158,6 @@ public class OderVStrategy extends AbstractScoreRuleStrategy {
try {
HashMap<String, Object> map = new HashMap<>();
map.put("orderId", orderId);
// TODO:增加订单号和唯一键
memberUserScoreApi.operateScore(MemberUserScoreOperateReqDTO.builder()
.memberId(userId)
.scoreCount(scoreCount)
......
package cn.iocoder.yudao.module.member.mq.consumer.score.core;
import cn.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQuery;
import cn.iocoder.yudao.module.member.api.score.MemberUserScoreApi;
import cn.iocoder.yudao.module.member.api.score.dto.MemberUserScoreOperateReqDTO;
import cn.iocoder.yudao.module.member.dal.dataobject.scoreLog.MemberUserScoreLogDO;
import cn.iocoder.yudao.module.member.dal.dataobject.scoreRule.ScoreRuleDO;
import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
import cn.iocoder.yudao.module.member.enums.ScoreRuleStatusEnum;
import cn.iocoder.yudao.module.member.enums.ScoreRuleTypeEnum;
import cn.iocoder.yudao.module.member.enums.ScoreSourceTypeEnum;
import cn.iocoder.yudao.module.member.mq.message.ScoreMessage;
import cn.iocoder.yudao.module.member.service.scoreLog.MemberUserScoreLogService;
import cn.iocoder.yudao.module.member.service.scoreRule.ScoreRuleService;
import cn.iocoder.yudao.module.member.service.user.MemberUserService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import cn.iocoder.yudao.module.member.util.ReferralCodeUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
/**
* @author zhangfeng
......@@ -33,45 +27,28 @@ public class RecommendStrategy extends AbstractScoreRuleStrategy {
private MemberUserScoreApi memberUserScoreApi;
@Resource
private MemberUserService memberUserService;
@Resource
private MemberUserScoreLogService memberUserScoreLogService;
public RecommendStrategy(ScoreRuleService scoreRuleService) {
super(scoreRuleService);
public RecommendStrategy(ScoreRuleService scoreRuleService, MemberUserScoreLogService memberUserScoreLogService, MemberUserService memberUserService) {
super(scoreRuleService, memberUserScoreLogService, memberUserService);
}
@Override
public void addScore(ScoreMessage message) {
Long userId = message.getUserId();
// 根据推荐码获取推荐用户id
Long userId = ReferralCodeUtils.getUserId(message.getReferralCode());
log.info("Received Recommend message,userID:{}", userId);
ScoreRuleDO scoreRuleDO = scoreRuleService.selectOne(new LambdaQuery<ScoreRuleDO>()
.eq(ScoreRuleDO::getType, ScoreRuleTypeEnum.RECOMMEND.getValue())
.eq(ScoreRuleDO::getStatus, ScoreRuleStatusEnum.ENABLED.getValue()));
ScoreRuleDO scoreRuleDO = scoreRuleService.getEnableScoreRuleByType(ScoreRuleTypeEnum.RECOMMEND);
if (scoreRuleDO == null) {
log.info("Recommend rule is not exist,userID:{}", userId);
return;
}
// 是否过期,或者活动还没开始
if (!scoreRuleDO.getEndTime().after(new Date()) || !scoreRuleDO.getStartTime().before(new Date())) {
log.info("Recommend listener: The score rule has expired,scoreRuleID:{}", scoreRuleDO.getId());
return;
}
MemberUserDO memberUserDO = memberUserService.getUser(userId);
if (memberUserDO == null) {
log.info("Recommend listener: The user does not exist,userID:{}", userId);
log.info("Recommend listener: The recommend user does not exist,userID:{}", userId);
return;
}
// 校验累计最高分
Integer userScoreTotalCount = 0;
LambdaQueryWrapper<MemberUserScoreLogDO> scoreLogQueryWrapper = new LambdaQueryWrapper<>();
scoreLogQueryWrapper.eq(MemberUserScoreLogDO::getMemberId, userId)
.eq(MemberUserScoreLogDO::getRuleId, scoreRuleDO.getId());
List<MemberUserScoreLogDO> memberUserScoreLogs = memberUserScoreLogService.selectList(scoreLogQueryWrapper);
if (CollUtil.isNotEmpty(memberUserScoreLogs)) {
for (MemberUserScoreLogDO memberUserScoreLog : memberUserScoreLogs) {
userScoreTotalCount += memberUserScoreLog.getScoreCount();
}
}
Integer userScoreTotalCount = getUserScoreTotalCount(scoreRuleDO.getId(), userId);
if (userScoreTotalCount >= scoreRuleDO.getMaxScoreTotal()) {
log.info("Recommend listener: The user has reached the maximum score,userId:{},scoreRuleId:{}", userId, scoreRuleDO.getId());
return;
......
package cn.iocoder.yudao.module.member.mq.consumer.score.core;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQuery;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import cn.iocoder.yudao.module.member.api.score.MemberUserScoreApi;
import cn.iocoder.yudao.module.member.api.score.dto.MemberUserScoreOperateReqDTO;
import cn.iocoder.yudao.module.member.dal.dataobject.scoreRule.ScoreRuleDO;
import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
import cn.iocoder.yudao.module.member.enums.ScoreRuleStatusEnum;
import cn.iocoder.yudao.module.member.enums.ScoreRuleTypeEnum;
import cn.iocoder.yudao.module.member.enums.ScoreSourceTypeEnum;
import cn.iocoder.yudao.module.member.mq.message.ScoreMessage;
import cn.iocoder.yudao.module.member.service.scoreLog.MemberUserScoreLogService;
import cn.iocoder.yudao.module.member.service.scoreRule.ScoreRuleService;
import cn.iocoder.yudao.module.member.service.user.MemberUserService;
import cn.iocoder.yudao.module.member.vo.scoreRule.extra.ScoreRuleRegisterExtraVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
/**
......@@ -29,32 +29,32 @@ public class RegisterStrategy extends AbstractScoreRuleStrategy {
@Resource
private MemberUserService memberUserService;
public RegisterStrategy(ScoreRuleService scoreRuleService) {
super(scoreRuleService);
public RegisterStrategy(ScoreRuleService scoreRuleService, MemberUserScoreLogService memberUserScoreLogService, MemberUserService memberUserService) {
super(scoreRuleService, memberUserScoreLogService, memberUserService);
}
@Override
public void addScore(ScoreMessage message) {
Long userId = message.getUserId();
log.info("Received register message,userID:{}", userId);
ScoreRuleDO scoreRuleDO = scoreRuleService.selectOne(new LambdaQuery<ScoreRuleDO>()
.eq(ScoreRuleDO::getType, ScoreRuleTypeEnum.REGISTER.getValue())
.eq(ScoreRuleDO::getStatus, ScoreRuleStatusEnum.ENABLED.getValue()));
ScoreRuleDO scoreRuleDO = scoreRuleService.getEnableScoreRuleByType(ScoreRuleTypeEnum.REGISTER);
if (scoreRuleDO == null) {
log.info("Register rule is not exist,userID:{}", userId);
return;
}
// 是否过期,或者活动还没开始
if (!scoreRuleDO.getEndTime().after(new Date()) || !scoreRuleDO.getStartTime().before(new Date())) {
log.info("Register listener: The score rule has expired,scoreRuleID:{}", scoreRuleDO.getId());
return;
}
MemberUserDO memberUserDO = memberUserService.getUser(userId);
if (memberUserDO == null) {
log.info("Register listener: The user does not exist,userID:{}", userId);
return;
}
//TODO:校验注册入口,目前表没加
// 校验注册平台
ScoreRuleRegisterExtraVO scoreRuleRegisterExtraVO = JsonUtils.parseObject(scoreRuleDO.getExtra(), ScoreRuleRegisterExtraVO.class);
if (scoreRuleRegisterExtraVO != null && !"2,3".equals(scoreRuleRegisterExtraVO.getRegisterPlatform())) {
if (!scoreRuleRegisterExtraVO.getRegisterPlatform().contains(String.valueOf(message.getRegisterPlatform()))) {
log.info("Register listener: The register platform does not match,userID:{}", userId);
return;
}
}
try {
HashMap<String, Object> map = new HashMap<>();
map.put("userId", userId);
......
......@@ -8,5 +8,4 @@ import cn.iocoder.yudao.module.member.mq.message.ScoreMessage;
public interface ScoreRuleStrategy {
void addScore(ScoreMessage message);
ScoreRuleTypeEnum getStrategyScoreRuleType();
void refreshScoreRule(ScoreRuleTypeEnum scoreRuleType);
}
......@@ -21,7 +21,7 @@ public class ScoreMessage extends AbstractStreamMessage {
*/
private Long orderId;
/**
* userID:注册,推荐必填(加分的人)
* userID:注册必填
*/
private Long userId;
/**
......@@ -29,21 +29,25 @@ public class ScoreMessage extends AbstractStreamMessage {
*/
private Long recommendUserId;
/**
* 中文名:注册,推荐必填,推荐时填推荐人的信息
* 推荐码:推荐必填
*/
private String referralCode;
/**
* 中文名:注册必填
*/
private String userNameZh;
/**
* 英文名:注册,推荐必填,推荐时填推荐人的信息
* 英文名:注册必填
*/
private String userNameEn;
/**
* userID:注册,推荐必填,推荐时填推荐人的信息
* 电话:注册必填
*/
private String phone;
/**
* 推荐码:推荐必填
* 注册平台:注册必填
*/
private String recommendCode;
private Integer registerPlatform;
@Override
public String getStreamKey() {
......
......@@ -8,6 +8,7 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
/**
* @author zhangfeng
*/
......@@ -16,6 +17,7 @@ import javax.annotation.Resource;
public class ScoreProducer implements ScoreProducerApi {
@Resource
private RedisMQTemplate redisMQTemplate;
@Override
public void sendOderMessage(ScoreRuleTypeEnum scoreRuleType, Long orderId) {
ScoreMessage message = ScoreMessage.builder()
......@@ -26,12 +28,25 @@ public class ScoreProducer implements ScoreProducerApi {
}
@Override
public void sendRecommendMessage(ScoreRuleTypeEnum scoreRuleType, Long userId) {
public void sendRecommendMessage(ScoreRuleTypeEnum scoreRuleType, Long userId, String referralCode) {
ScoreMessage message = ScoreMessage.builder()
.scoreRuleType(scoreRuleType)
.recommendUserId(userId)
.referralCode(referralCode)
.build();
redisMQTemplate.send(message);
}
@Override
public void sendRegisterMessage(ScoreRuleTypeEnum scoreRuleType, Long userId) {
public void sendRegisterMessage(ScoreRuleTypeEnum scoreRuleType, Long userId, String userNameZh, String userNameEn, String phone, Integer registerPlatform) {
ScoreMessage message = ScoreMessage.builder()
.scoreRuleType(scoreRuleType)
.userId(userId)
.userNameZh(userNameZh)
.userNameEn(userNameEn)
.phone(phone)
.registerPlatform(registerPlatform)
.build();
redisMQTemplate.send(message);
}
}
......@@ -13,10 +13,12 @@ import cn.iocoder.yudao.framework.security.core.authentication.MultiUsernamePass
import cn.iocoder.yudao.module.ecw.api.internalMessage.ClientInternalMessageApi;
import cn.iocoder.yudao.module.ecw.api.internalMessage.dto.InternalMessageCreateDto;
import cn.iocoder.yudao.module.ecw.api.paramValid.ParamValidatorApi;
import cn.iocoder.yudao.module.member.api.ScoreProducerApi;
import cn.iocoder.yudao.module.member.controller.app.auth.vo.*;
import cn.iocoder.yudao.module.member.convert.auth.AuthConvert;
import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
import cn.iocoder.yudao.module.member.dal.mysql.user.MemberUserMapper;
import cn.iocoder.yudao.module.member.enums.ScoreRuleTypeEnum;
import cn.iocoder.yudao.module.member.enums.UserOperationLogTypeEnum;
import cn.iocoder.yudao.module.member.service.user.MemberUserService;
import cn.iocoder.yudao.module.member.service.userOperationLog.UserOperationLogService;
......@@ -94,6 +96,8 @@ public class MemberAuthServiceImpl implements MemberAuthService {
@Resource
private ParamValidatorApi paramValidatorApi;
@Resource
private ScoreProducerApi scoreProducerApi;
@Override
public UserDetails loadUserByUsername(String mobile) throws UsernameNotFoundException {
......@@ -111,13 +115,13 @@ public class MemberAuthServiceImpl implements MemberAuthService {
// 校验验证码
smsCodeApi.useSmsCode(AuthConvert.INSTANCE.convert(reqVO, SmsSceneEnum.MEMBER_REG.getScene(), userIp));
MemberUserDO userByMobile = userService.checkPhoneUnique(reqVO.getAreaCode(),reqVO.getMobile());
MemberUserDO userByMobile = userService.checkPhoneUnique(reqVO.getAreaCode(), reqVO.getMobile());
if (userByMobile != null) {
throw exception(MEMBER_USER_MOBILE_EXIST);
}
// 获得获得注册用户
MemberUserDO user = userService.createUser(reqVO.getMobile(), userIp, reqVO.getPassword(),reqVO.getAreaCode(), reqVO.getEnglishName(), reqVO.getReferralCode());
MemberUserDO user = userService.createUser(reqVO.getMobile(), userIp, reqVO.getPassword(), reqVO.getAreaCode(), reqVO.getEnglishName(), reqVO.getReferralCode(), reqVO.getRegisterPlatform());
Assert.notNull(user, "创建用户失败,结果为空");
//记录日志
......@@ -140,8 +144,8 @@ public class MemberAuthServiceImpl implements MemberAuthService {
@Override
public boolean checkPhoneUnique(String areaCode, String mobile) {
MemberUserDO memberUserDO=userService.checkPhoneUnique(areaCode,mobile);
return memberUserDO!=null;
MemberUserDO memberUserDO = userService.checkPhoneUnique(areaCode, mobile);
return memberUserDO != null;
}
@Override
......@@ -160,7 +164,7 @@ public class MemberAuthServiceImpl implements MemberAuthService {
smsCodeApi.useSmsCode(AuthConvert.INSTANCE.convert(reqVO, SmsSceneEnum.MEMBER_LOGIN.getScene(), userIp));
// 获得获得注册用户
MemberUserDO user = userService.createUserIfAbsent(reqVO.getMobile(),reqVO.getAreaCode(), userIp);
MemberUserDO user = userService.createUserIfAbsent(reqVO.getMobile(), reqVO.getAreaCode(), userIp, reqVO.getLoginPlatform());
Assert.notNull(user, "获取用户失败,结果为空");
// 执行登陆
......@@ -273,6 +277,9 @@ public class MemberAuthServiceImpl implements MemberAuthService {
loginLogApi.createLoginLog(reqDTO);
// 更新最后登录时间
if (user != null && Objects.equals(LoginResultEnum.SUCCESS.getResult(), loginResult.getResult())) {
// 注册,推荐积分规则触发判断
scoreRuleCheck(user);
userService.updateUserLogin(user.getId(), getClientIP());
}
......@@ -452,14 +459,14 @@ public class MemberAuthServiceImpl implements MemberAuthService {
@Override
public void sendEmailCode(Long loginUserId, AppEmailReqVO reqVO) {
MemberUserDO userVo = userService.getUserByEmail(reqVO.getEmail());
if(userVo!=null){
if (userVo != null) {
throw exception(USER_EMAIL_ALREADY_EXISTS);
}
MemberUserDO user = userService.getUser(loginUserId);
Map<String,String> tempalteParam = new HashMap<>();
tempalteParam.put("name",user.getEnglishName());
Map<String, String> tempalteParam = new HashMap<>();
tempalteParam.put("name", user.getEnglishName());
//todo 生成验证码逻辑
tempalteParam.put("code","9999");
tempalteParam.put("code", "9999");
tempalteParam.put("date", DateUtils.getDate());
MailTemplateSendReqVO reqVO1 = new MailTemplateSendReqVO();
reqVO1.setTemplateCode("bindEmail");
......@@ -489,11 +496,11 @@ public class MemberAuthServiceImpl implements MemberAuthService {
if (user == null) {
throw exception(USER_NOT_EXISTS);
}
if(StringUtils.isBlank(user.getPassword())){
if (StringUtils.isBlank(user.getPassword())) {
return user;
}
// 参数:未加密密码,编码后的密码
if (!passwordEncoder.matches(oldPassword,user.getPassword())) {
if (!passwordEncoder.matches(oldPassword, user.getPassword())) {
throw exception(USER_PASSWORD_FAILED);
}
return user;
......@@ -512,11 +519,11 @@ public class MemberAuthServiceImpl implements MemberAuthService {
if (user == null) {
throw exception(USER_NOT_EXISTS);
}
if(StringUtils.isBlank(user.getControlPassword())){
if (StringUtils.isBlank(user.getControlPassword())) {
return user;
}
// 参数:未加密密码,编码后的密码
if (!passwordEncoder.matches(oldPassword,user.getControlPassword())) {
if (!passwordEncoder.matches(oldPassword, user.getControlPassword())) {
throw exception(USER_PASSWORD_FAILED);
}
return user;
......@@ -543,4 +550,16 @@ public class MemberAuthServiceImpl implements MemberAuthService {
loginLogApi.createLoginLog(reqDTO);
}
private void scoreRuleCheck(MemberUserDO user) {
// 首次登陆发获取注册积分
if (user.getLoginDate() == null) {
scoreProducerApi.sendRegisterMessage(ScoreRuleTypeEnum.REGISTER, user.getId(), user.getNickname(), user.getEnglishName(), user.getMobile(), user.getRegisterPlatform());
}
// 首次登陆且有推荐码获取推荐积分
if (user.getLoginDate() == null && user.getReferralCode() != null) {
scoreProducerApi.sendRecommendMessage(ScoreRuleTypeEnum.RECOMMEND, user.getId(), user.getReferralCode());
}
}
}
......@@ -7,6 +7,8 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.service.IService;
import cn.iocoder.yudao.framework.mybatis.core.vo.PageVO;
import cn.iocoder.yudao.module.member.dal.dataobject.scoreRule.ScoreRuleDO;
import cn.iocoder.yudao.module.member.enums.ScoreRuleTypeEnum;
import cn.iocoder.yudao.module.member.enums.TransportTypeEnum;
import cn.iocoder.yudao.module.member.vo.scoreRule.*;
/**
......@@ -18,6 +20,7 @@ public interface ScoreRuleService extends IService<ScoreRuleDO> {
/**
* 创建积分规则
*
* @param createReqVO 创建信息
* @return 编号
*/
......@@ -25,12 +28,14 @@ public interface ScoreRuleService extends IService<ScoreRuleDO> {
/**
* 更新积分规则
*
* @param updateReqVO 更新信息
*/
void updateScoreRule(@Valid ScoreRuleUpdateReqVO updateReqVO);
/**
* 删除积分规则
*
* @param id 编号
*/
void deleteScoreRule(Long id);
......@@ -62,6 +67,7 @@ public interface ScoreRuleService extends IService<ScoreRuleDO> {
/**
* 获得积分规则列表, 用于 Excel 导出
*
* @param query 查询
* @return 积分规则列表
*/
......@@ -69,6 +75,7 @@ public interface ScoreRuleService extends IService<ScoreRuleDO> {
/**
* 积分规则启用关闭
*
* @param scoreRuleStatusReqVO 积分规则状态
* @return
*/
......@@ -76,6 +83,7 @@ public interface ScoreRuleService extends IService<ScoreRuleDO> {
/**
* 积分规则复制
*
* @param id
* @return
*/
......@@ -83,6 +91,7 @@ public interface ScoreRuleService extends IService<ScoreRuleDO> {
/**
* 积分规则延期
*
* @param scoreDelayReqVO 积分规则延期
* @return
*/
......@@ -90,8 +99,24 @@ public interface ScoreRuleService extends IService<ScoreRuleDO> {
/**
* 根据运输方式获取已启用订单V值规则
*
* @param transportType
* @return
*/
ScoreRuleDO getEnabledOrderVScoreRuleByTransportType(Integer transportType);
/**
* 根据类型获取已启用积分规则
* @param scoreRuleType
* @return
*/
ScoreRuleDO getEnableScoreRuleByType(ScoreRuleTypeEnum scoreRuleType);
/**
* 根据类型获取已启用积分规则(带运输类型)
* @param scoreRuleType
* @param transportType
* @return
*/
ScoreRuleDO getEnableScoreRuleByType(ScoreRuleTypeEnum scoreRuleType, TransportTypeEnum transportType);
}
......@@ -12,6 +12,7 @@ import cn.iocoder.yudao.framework.mybatis.core.service.AbstractService;
import cn.iocoder.yudao.module.member.convert.scoreRule.ScoreRuleConvert;
import cn.iocoder.yudao.module.member.dal.dataobject.scoreRule.ScoreRuleDO;
import cn.iocoder.yudao.module.member.dal.mysql.scoreRule.ScoreRuleMapper;
import cn.iocoder.yudao.module.member.dal.redis.scoreRule.ScoreRuleRedisDao;
import cn.iocoder.yudao.module.member.enums.ScoreRuleStatusEnum;
import cn.iocoder.yudao.module.member.enums.ScoreRuleTypeEnum;
import cn.iocoder.yudao.module.member.enums.TransportTypeEnum;
......@@ -41,6 +42,8 @@ public class ScoreRuleServiceImpl extends AbstractService<ScoreRuleMapper, Score
@Resource
private ScoreRuleMapper scoreRuleMapper;
@Resource
private ScoreRuleRedisDao scoreRuleRedisDao;
@Override
public Long createScoreRule(ScoreRuleCreateReqVO createReqVO) {
......@@ -52,6 +55,7 @@ public class ScoreRuleServiceImpl extends AbstractService<ScoreRuleMapper, Score
Integer scoreRuleType = scoreRule.getType();
verifyAndSetExtraDO(createReqVO, scoreRuleType, scoreRule);
scoreRuleMapper.insert(scoreRule);
scoreRuleRedisDao.deleteEnableScoreRule(scoreRule.getType());
// 返回
return scoreRule.getId();
}
......@@ -117,6 +121,7 @@ public class ScoreRuleServiceImpl extends AbstractService<ScoreRuleMapper, Score
verifyAndSetExtraDO(updateReqVO, updateReqVO.getType(), scoreRule);
// 更新
scoreRuleMapper.updateById(scoreRule);
scoreRuleRedisDao.deleteEnableScoreRule(scoreRule.getType());
}
/**
......@@ -289,6 +294,7 @@ public class ScoreRuleServiceImpl extends AbstractService<ScoreRuleMapper, Score
throw exception(SCORE_RULE_UPDATE_ERROR);
}
scoreRuleMapper.updateById(upScoreRuleDO);
scoreRuleRedisDao.deleteEnableScoreRule(scoreRuleDO.getType());
}
@Override
......@@ -344,4 +350,56 @@ public class ScoreRuleServiceImpl extends AbstractService<ScoreRuleMapper, Score
}
return null;
}
@Override
public ScoreRuleDO getEnableScoreRuleByType(ScoreRuleTypeEnum scoreRuleType) {
ScoreRuleDO enableScoreRule;
enableScoreRule = scoreRuleRedisDao.getEnableScoreRule(scoreRuleType);
if (enableScoreRule == null) {
enableScoreRule = selectOne(new LambdaQuery<ScoreRuleDO>()
.eq(ScoreRuleDO::getType, scoreRuleType.getValue())
.eq(ScoreRuleDO::getStatus, ScoreRuleStatusEnum.ENABLED.getValue()));
if (enableScoreRule == null) {
return null;
}
// 校验一下活动开始结束时间
if (!enableScoreRule.getEndTime().after(new Date()) || !enableScoreRule.getStartTime().before(new Date())) {
return null;
}
scoreRuleRedisDao.setEnableScoreRule(enableScoreRule);
} else {
if (!enableScoreRule.getEndTime().after(new Date()) || !enableScoreRule.getStartTime().before(new Date())) {
return null;
}
}
return enableScoreRule;
}
@Override
public ScoreRuleDO getEnableScoreRuleByType(ScoreRuleTypeEnum scoreRuleType, TransportTypeEnum transportType) {
ScoreRuleDO enableScoreRule;
switch (scoreRuleType) {
case ORDER_V:
enableScoreRule = scoreRuleRedisDao.getEnableScoreRule(scoreRuleType, transportType);
if (enableScoreRule == null) {
enableScoreRule = getEnabledOrderVScoreRuleByTransportType(transportType.getValue());
if (enableScoreRule == null) {
return null;
}
if (!enableScoreRule.getEndTime().after(new Date()) || !enableScoreRule.getStartTime().before(new Date())) {
return null;
}
scoreRuleRedisDao.setEnableScoreRule(enableScoreRule);
} else {
if (!enableScoreRule.getEndTime().after(new Date()) || !enableScoreRule.getStartTime().before(new Date())) {
return null;
}
}
return enableScoreRule;
case RECOMMEND:
case REGISTER:
return getEnableScoreRuleByType(scoreRuleType);
}
return null;
}
}
......@@ -29,9 +29,10 @@ public interface MemberUserService {
* @return 用户对象
*/
MemberUserDO getUserByMobile(String mobile);
MemberUserDO checkPhoneUnique(String areaCode,String mobile);
MemberUserDO getUserByMobile(String areaCode,String mobile);
MemberUserDO checkPhoneUnique(String areaCode, String mobile);
MemberUserDO getUserByMobile(String areaCode, String mobile);
MemberUserDO getUserByEmail(String email);
......@@ -43,7 +44,7 @@ public interface MemberUserService {
* @param registerIp 注册 IP
* @return 用户对象
*/
MemberUserDO createUserIfAbsent(String mobile, String areaCode, String registerIp);
MemberUserDO createUserIfAbsent(String mobile, String areaCode, String registerIp,Integer platform);
/****
* 基于手机号创建用户
......@@ -53,7 +54,7 @@ public interface MemberUserService {
* @param referralCode
* @return
*/
MemberUserDO createUser(String mobile, String registerIp, String password, String areaCode, String englishName, String referralCode);
MemberUserDO createUser(String mobile, String registerIp, String password, String areaCode, String englishName, String referralCode, Integer registerPlatform);
/**
* 更新用户的最后登陆信息
......@@ -75,7 +76,7 @@ public interface MemberUserService {
* 通过用户 ID 查询用户
*
* @param id 用户ID
* @return 用户对象信息,包括公司信息
* @return 用户对象信息, 包括公司信息
*/
MemberUserDO info(Long id);
......@@ -182,18 +183,18 @@ public interface MemberUserService {
* 会员发出的订单统计
* TODO 分布式系统可能需要在分库分表时将此方法实现切换到订单模块,现在未避免循环依赖故将实现方法放在此处,也可用使用监听去实现
*
* @param mobile 用户手机号
* @param userId 用户ID
* @param mobile 用户手机号
* @param userId 用户ID
* @param customerContactsIds 客户联系人ids
* @return 会员发出的订单数量统计
*/
Integer appIssuedOrderCount(String mobile,Long userId,Collection<Long> customerContactsIds);
Integer appIssuedOrderCount(String mobile, Long userId, Collection<Long> customerContactsIds);
/**
* 会员收到的订单统计
* TODO 分布式系统可能需要在分库分表时将此方法实现切换到订单模块,现在未避免循环依赖故将实现方法放在此处,也可用使用监听去实现
*
* @param phone 会员电话
* @param phone 会员电话
* @param customerContactsIds 客户联系人ids
* @return 会员收到的订单数量统计
*/
......@@ -203,8 +204,8 @@ public interface MemberUserService {
* 会员收到的订单统计
* TODO 分布式系统可能需要在分库分表时将此方法实现切换到订单模块,现在未避免循环依赖故将实现方法放在此处,也可用使用监听去实现
*
* @param userId 用户ID
* @param phone 会员电话
* @param userId 用户ID
* @param phone 会员电话
* @param customerContactsIds 客户联系人ids
* @return 会员收到的订单数量统计
*/
......
......@@ -153,7 +153,7 @@ public class MemberUserServiceImpl implements MemberUserService {
}
@Override
public MemberUserDO createUserIfAbsent(String mobile, String areaCode, String registerIp) {
public MemberUserDO createUserIfAbsent(String mobile, String areaCode, String registerIp, Integer platform) {
try {
String mobileCode = areaCode + StrUtil.COLON + mobile;
......@@ -172,7 +172,7 @@ public class MemberUserServiceImpl implements MemberUserService {
}
String englishName = maskMobileNumber(mobile);
// 用户不存在,则进行创建
user = this.createUser(mobile, registerIp, null, areaCode, englishName, null);
user = this.createUser(mobile, registerIp, null, areaCode, englishName, null, platform);
//记录日志
UserOperationLogCreateReqVO userOperationLogCreateReqVO = new UserOperationLogCreateReqVO();
......@@ -202,7 +202,7 @@ public class MemberUserServiceImpl implements MemberUserService {
@Override
@Transactional(rollbackFor = Exception.class)
public MemberUserDO createUser(String mobile, String registerIp, String password, String areacode, String englishName, String referralCode) {
public MemberUserDO createUser(String mobile, String registerIp, String password, String areacode, String englishName, String referralCode, Integer registerPlatform) {
// 生成密码
/* if (StrUtil.isBlank(password)) {
password = IdUtil.fastSimpleUUID();
......@@ -223,6 +223,7 @@ public class MemberUserServiceImpl implements MemberUserService {
user.setNickname(englishName);
user.setCode(getNextMemberCode());
user.setReferralCode(referralCode);
user.setRegisterPlatform(registerPlatform);
memberUserMapper.insert(user);
//站内信
InternalMessageCreateDto dto = InternalMessageCreateDto.builder().toIdList(Arrays.asList(user.getId()))
......@@ -563,7 +564,7 @@ public class MemberUserServiceImpl implements MemberUserService {
long limit = 500;
memberUserMapper.clearMemberCode();
redisHelper.delete("memberCode:max:number");
while(true) {
while (true) {
List<MemberUserDO> result = this.getByCursor(startUserId, limit);
if (CollectionUtils.isEmpty(result)) {
break;
......
package cn.iocoder.yudao.module.member.util;
public class ReferralCodeUtils {
/**
* 根据用户id生成推荐码
*/
public static String generateReferralCode(Long userId) {
return userId.toString();
}
/**
* 根据推荐码获取用户id
*/
public static Long getUserId(String referralCode) {
return Long.parseLong(referralCode);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment