Commit fc70713f authored by zhangfeng's avatar zhangfeng

Merge branch 'refs/heads/feature_member_score_rule_feat' into feature_member_score

parents 784b37c2 6afdaa40
......@@ -11,4 +11,6 @@ public interface ScoreProducerApi {
void sendRecommendMessage(ScoreRuleTypeEnum scoreRuleType, Long userId, String referralCode);
void sendRegisterMessage(ScoreRuleTypeEnum scoreRuleType, Long userId, String userNameZh, String userNameEn, String phone, Integer registerPlatform);
void sendShareMessage(ScoreRuleTypeEnum scoreRuleType, Long userId, Long ruleId, String ipAddr);
}
......@@ -128,7 +128,6 @@ public class ScoreRuleController {
@GetMapping("/test-score-rule")
@ApiOperation("测试订单V值触发")
public CommonResult<Void> testScoreRule(@RequestParam Long orderId, @RequestParam String orderNo) {
//applicationContext.publishEvent(new OrderInShippingEvent(orderId, orderNo));
scoreProducerApi.sendOderMessage(ScoreRuleTypeEnum.ORDER_V, orderId <= 0 ? null : orderId, orderNo);
return success(null);
}
......
package cn.iocoder.yudao.module.member.controller.admin.scoreRule;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.vo.PageVO;
import cn.iocoder.yudao.module.member.dal.dataobject.ScoreRuleShareRecord.ScoreRuleShareRecordDO;
import cn.iocoder.yudao.module.member.service.ScoreRuleShareRecord.ScoreRuleShareRecordService;
import cn.iocoder.yudao.module.member.vo.ScoreRuleShareRecord.ScoreRuleShareRecordDetailReqVO;
import cn.iocoder.yudao.module.member.vo.ScoreRuleShareRecord.ScoreRuleShareRecordDetailVO;
import cn.iocoder.yudao.module.member.vo.ScoreRuleShareRecord.ScoreRuleShareRecordPageVO;
import cn.iocoder.yudao.module.member.vo.ScoreRuleShareRecord.ScoreRuleShareRecordQueryVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@Validated
@RestController
@Api(tags = "管理后台 - 分享记录")
@RequestMapping("/member/score-rule/share-record")
public class ScoreRuleShareRecordController {
@Resource
private ScoreRuleShareRecordService scoreRuleShareRecordService;
@PostMapping("/detail")
@ApiOperation("获得分享记录详情")
public CommonResult<PageResult<ScoreRuleShareRecordDetailVO>> getRuleShareRecordDetail(@Valid @RequestBody ScoreRuleShareRecordDetailReqVO reqVO) {
return success(scoreRuleShareRecordService.getRuleShareRecordDetail(reqVO));
}
@PostMapping("/page")
@ApiOperation("获得分享记录分页")
public CommonResult<PageResult<ScoreRuleShareRecordPageVO>> getRuleShareRecordPage(@Valid @RequestBody ScoreRuleShareRecordQueryVO query) {
return success(scoreRuleShareRecordService.getRuleShareRecordPage(query));
}
}
package cn.iocoder.yudao.module.member.controller.app.scoreRule;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.vo.PageVO;
import cn.iocoder.yudao.framework.common.util.ip.IPHelper;
import cn.iocoder.yudao.framework.idempotent.core.annotation.Idempotent;
import cn.iocoder.yudao.module.member.api.ScoreProducerApi;
import cn.iocoder.yudao.module.member.controller.app.scoreRule.vo.AppScoreRuleBackDetailVO;
import cn.iocoder.yudao.module.member.controller.app.scoreRule.vo.AppScoreRuleListBackVO;
import cn.iocoder.yudao.module.member.controller.app.scoreRule.vo.AppScoreRuleListReqVO;
import cn.iocoder.yudao.module.member.enums.ScoreRuleTypeEnum;
import cn.iocoder.yudao.module.member.service.scoreRule.ScoreRuleService;
import cn.iocoder.yudao.module.member.vo.scoreRule.IdReqVo;
import cn.iocoder.yudao.module.member.vo.scoreRule.ScoreRuleBackVO;
import cn.iocoder.yudao.module.member.vo.scoreRule.ScoreRuleQueryVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.context.ApplicationContext;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.validation.Valid;
import java.util.List;
......@@ -43,6 +40,7 @@ public class AppScoreRuleController {
@PostMapping("/get")
@ApiOperation("客户端获得积分规则详情")
@Idempotent(timeout = 5)
public CommonResult<AppScoreRuleBackDetailVO> getScoreRule(@Valid @RequestBody IdReqVo idReqVo) {
AppScoreRuleBackDetailVO scoreRuleBackDetailVO = scoreRuleService.appGetScoreRule(idReqVo.getId());
return success(scoreRuleBackDetailVO);
......@@ -50,11 +48,21 @@ public class AppScoreRuleController {
@PostMapping("/list")
@ApiOperation("客户端获得积分规则列表")
@Idempotent(timeout = 5)
public CommonResult<List<AppScoreRuleListBackVO>> getScoreRuleList(@Valid @RequestBody AppScoreRuleListReqVO reqVO) {
List<AppScoreRuleListBackVO> list = scoreRuleService.appGetScoreRuleList(reqVO);
return success(list);
}
@GetMapping("/trigger/share")
@ApiOperation("分享规则触发")
@Idempotent(timeout = 5)
public void triggerShareScoreRule(HttpServletRequest request, @RequestParam Long userId, @RequestParam Long ruleId) {
if (ruleId == null || userId == null) {
return;
}
scoreProducerApi.sendShareMessage(ScoreRuleTypeEnum.SHARE, userId, ruleId, IPHelper.getIpAddr(request));
}
//@PostMapping("/page")
//@ApiOperation("获得积分规则分页")
//public CommonResult<PageResult<ScoreRuleBackVO>> getScoreRulePage(@Valid @RequestBody ScoreRuleQueryVO query, PageVO page) {
......
package cn.iocoder.yudao.module.member.controller.app.scoreRule;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.idempotent.core.annotation.Idempotent;
import cn.iocoder.yudao.module.member.service.ScoreRuleShareRecord.ScoreRuleShareRecordService;
import cn.iocoder.yudao.module.member.vo.ScoreRuleShareRecord.ScoreRuleShareRecordCreateReqVO;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import javax.annotation.Resource;
import javax.validation.Valid;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@Validated
@RestController
@Api(tags = "管理后台 - 分享记录")
@RequestMapping("/member/score-rule/share-record")
public class AppScoreRuleShareRecordController {
@Resource
private ScoreRuleShareRecordService scoreRuleShareRecordService;
@PostMapping("/create")
@ApiOperation("创建分享记录")
@Idempotent(timeout = 5)
public CommonResult<Long> createRuleShareRecord(@Valid @RequestBody ScoreRuleShareRecordCreateReqVO createReqVO) {
return success(scoreRuleShareRecordService.createRuleShareRecord(createReqVO));
}
}
......@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.member.controller.app.scoreRule.vo;
import cn.iocoder.yudao.module.member.vo.scoreRule.extra.ScoreRuleOrderVExtraVO;
import cn.iocoder.yudao.module.member.vo.scoreRule.extra.ScoreRuleShareExtraVO;
import cn.iocoder.yudao.module.member.vo.scoreRule.extra.ScoreRulerRecommendExtraVO;
import com.fasterxml.jackson.annotation.JsonInclude;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
......@@ -14,6 +15,7 @@ import lombok.Data;
*/
@Data
@ApiModel("客户端 - 积分规则列表 Response VO")
@JsonInclude(JsonInclude.Include.NON_NULL)
public class AppScoreRuleListBackVO {
@ApiModelProperty(value = "主键", required = true)
......@@ -46,6 +48,8 @@ public class AppScoreRuleListBackVO {
@ApiModelProperty(value = "推荐扩展字段")
private ScoreRulerRecommendExtraVO extraRecommend;
@ApiModelProperty(value = "推荐链接")
private String recommendUrl;
@ApiModelProperty(value = "分享扩展字段")
private ScoreRuleShareExtraVO extraShare;
@ApiModelProperty(value = "订单V值扩展字段")
......
......@@ -17,4 +17,7 @@ public class AppScoreRuleListReqVO {
@ApiModelProperty(value = "平台入口(2APP,3WEB)", required = true)
@NotNull(message = "平台入口不能为空")
private Integer platform;
@ApiModelProperty(value = "会员id", required = true)
@NotNull(message = "会员id不能为空")
private Long memberId;
}
package cn.iocoder.yudao.module.member.dal.dataobject.ScoreRuleShareRecord;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
import java.util.Date;
/**
* 分享记录 DO
*
* @author 系统管理员
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@TableName("score_rule_share_record")
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class ScoreRuleShareRecordDO extends BaseDO {
/**
* 主键
*/
@TableId
private Long id;
/**
* 分享编号
*/
private String code;
/**
* 会员id
*/
private Long memberId;
/**
* 积分规则id
*/
private Long ruleId;
/**
* 总积分
*/
private Integer totalScore;
/**
* 最后触发时间
*/
private Date lastTriggerTime;
}
package cn.iocoder.yudao.module.member.dal.mysql.ScoreRuleShareRecord;
import cn.iocoder.yudao.framework.mybatis.core.mapper.AbstractMapper;
import cn.iocoder.yudao.module.member.dal.dataobject.ScoreRuleShareRecord.ScoreRuleShareRecordDO;
import cn.iocoder.yudao.module.member.vo.ScoreRuleShareRecord.ScoreRuleShareRecordDetailVO;
import cn.iocoder.yudao.module.member.vo.ScoreRuleShareRecord.ScoreRuleShareRecordPageVO;
import cn.iocoder.yudao.module.member.vo.ScoreRuleShareRecord.ScoreRuleShareRecordQueryVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 分享记录 Mapper
*
* @author 系统管理员
*/
@Mapper
public interface ScoreRuleShareRecordMapper extends AbstractMapper<ScoreRuleShareRecordDO> {
List<ScoreRuleShareRecordPageVO> getScoreRuleShareRecordList(@Param("start") int start, @Param("size") int size, @Param("query") ScoreRuleShareRecordQueryVO query);
int countScoreRuleShareRecord(@Param("query") ScoreRuleShareRecordQueryVO query);
List<ScoreRuleShareRecordDetailVO> getRuleShareRecordDetail(@Param("start") int start, @Param("size") int size, @Param("id") Long id);
int countScoreRuleShareRecordDetail(@Param("id") Long id);
String getCurrentMaxShareRecordCode();
}
\ No newline at end of file
package cn.iocoder.yudao.module.member.mq.consumer.score.core;
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.ScoreRuleShareRecord.ScoreRuleShareRecordDO;
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.ScoreSourceTypeEnum;
import cn.iocoder.yudao.module.member.mq.message.ScoreMessage;
import cn.iocoder.yudao.module.member.service.ScoreRuleShareRecord.ScoreRuleShareRecordService;
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 lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.aop.framework.AopContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.util.Date;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.GET_LOCK_FAILED;
/**
* @author zhangfeng
*/
@Service
@Slf4j
public class ShareStrategy extends AbstractScoreRuleStrategy {
@Resource
private MemberUserService memberUserService;
@Resource
private ScoreRuleShareRecordService scoreRuleShareRecordService;
@Resource
private RedissonClient redissonClient;
public ShareStrategy(ScoreRuleService scoreRuleService, MemberUserScoreLogService memberUserScoreLogService, MemberUserService memberUserService, MemberUserScoreApi memberUserScoreApi) {
super(scoreRuleService, memberUserScoreLogService, memberUserService, memberUserScoreApi);
}
@Override
public void addScore(ScoreMessage message) {
Long userId = message.getUserId();
Long shareRuleId = message.getShareRuleId();
log.info("Received Share message,memberId:{},shareRuleId:{}", userId, shareRuleId);
// 根据分享人和规则id获取分享记录
ScoreRuleShareRecordDO scoreRuleShareRecordDO = scoreRuleShareRecordService.selectOne("member_id", userId, "rule_id", shareRuleId);
if (scoreRuleShareRecordDO == null) {
log.info("Share listener: The user not share the activity,userId:{},ruleId:{}", userId, shareRuleId);
return;
}
// 获取分享规则信息
ScoreRuleDO scoreRuleDO = scoreRuleService.getById(shareRuleId);
if (scoreRuleDO == null) {
log.info("Share rule is not exist,shareRuleId:{}", shareRuleId);
return;
}
// 校验规则
if (!verifyScoreRule(scoreRuleDO)) {
return;
}
// 校验累计最高分
Integer userScoreTotalCount = getUserScoreTotalCount(scoreRuleDO.getId(), userId);
if (scoreRuleDO.getMaxScoreTotal() > 0 && userScoreTotalCount >= scoreRuleDO.getMaxScoreTotal()) {
log.info("Share listener: The user has reached the maximum score,userId:{},scoreRuleId:{}", userId, scoreRuleDO.getId());
return;
}
// 更新积分和分享记录
String lockKey = "score:rule:share:lock:" + scoreRuleShareRecordDO.getId();
RLock lock = redissonClient.getLock(lockKey);
try {
if (!lock.tryLock(2, 10, TimeUnit.SECONDS)) {
throw exception(GET_LOCK_FAILED);
}
ShareStrategy currentProxy = (ShareStrategy) AopContext.currentProxy();
currentProxy.executeScoreRule(message.getTriggerIp(), shareRuleId, userId, scoreRuleDO, scoreRuleShareRecordDO);
} catch (InterruptedException e) {
throw exception(GET_LOCK_FAILED);
} finally {
lock.unlock();
}
log.info("Share rule add score success,ruleID:{},userID:{}", scoreRuleDO.getId(), userId);
}
@Transactional(rollbackFor = Exception.class)
public void executeScoreRule(String triggerIp, Long shareRuleId, Long userId, ScoreRuleDO scoreRuleDO, ScoreRuleShareRecordDO scoreRuleShareRecordDO) {
scoreRuleShareRecordDO.setTotalScore(scoreRuleShareRecordDO.getTotalScore() + scoreRuleDO.getGetScoreOnce());
scoreRuleShareRecordDO.setLastTriggerTime(new Date());
scoreRuleShareRecordService.updateById(scoreRuleShareRecordDO);
HashMap<String, Object> map = new HashMap<>(1);
map.put("scoreRuleId", shareRuleId);
memberUserScoreApi.operateScore(MemberUserScoreOperateReqDTO.builder()
.memberId(userId)
.scoreCount(scoreRuleDO.getGetScoreOnce())
.sourceType(ScoreSourceTypeEnum.SHARE)
.ruleId(scoreRuleDO.getId())
.uniqueId(userId + "_" + shareRuleId + "_" + triggerIp)
.expireDays(scoreRuleDO.getScorePeriod())
.extParam(map)
.build());
}
private boolean verifyScoreRule(ScoreRuleDO scoreRuleDO) {
if (scoreRuleDO.getStatus() != 1) {
log.info("Share listener: The rule is not enable,ruleId:{}", scoreRuleDO.getId());
return false;
}
if (scoreRuleDO.getType() != ScoreRuleTypeEnum.SHARE.getValue()) {
log.info("Share listener: Not share rule,ruleId:{}", scoreRuleDO.getId());
return false;
}
Date date = new Date();
if (date.before(scoreRuleDO.getStartTime()) || date.after(scoreRuleDO.getEndTime())) {
log.info("Share listener: The rule is not in the time range,ruleId:{}", scoreRuleDO.getId());
return false;
}
return true;
}
@Override
public ScoreRuleTypeEnum getStrategyScoreRuleType() {
return ScoreRuleTypeEnum.SHARE;
}
}
......@@ -16,6 +16,14 @@ public class ScoreMessage extends AbstractStreamMessage {
* 积分规则类型所有消息必填
*/
private ScoreRuleTypeEnum scoreRuleType;
/**
* 分享规则id
*/
private Long shareRuleId;
/**
* 分享规则id
*/
private String triggerIp;
/**
* 订单ID:订单V值消息必填
*/
......@@ -25,7 +33,7 @@ public class ScoreMessage extends AbstractStreamMessage {
*/
private String orderNo;
/**
* userID:注册必填
* userID:注册,分享必填
*/
private Long userId;
/**
......
......@@ -50,4 +50,15 @@ public class ScoreProducer implements ScoreProducerApi {
.build();
redisMQTemplate.send(message);
}
@Override
public void sendShareMessage(ScoreRuleTypeEnum scoreRuleType, Long userId, Long ruleId, String ipAddr) {
ScoreMessage message = ScoreMessage.builder()
.scoreRuleType(scoreRuleType)
.userId(userId)
.shareRuleId(ruleId)
.triggerIp(ipAddr)
.build();
redisMQTemplate.send(message);
}
}
package cn.iocoder.yudao.module.member.service.ScoreRuleShareRecord;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.service.IService;
import cn.iocoder.yudao.module.member.dal.dataobject.ScoreRuleShareRecord.ScoreRuleShareRecordDO;
import cn.iocoder.yudao.module.member.vo.ScoreRuleShareRecord.*;
import javax.validation.Valid;
/**
* 分享记录 Service 接口
*
* @author 系统管理员
*/
public interface ScoreRuleShareRecordService extends IService<ScoreRuleShareRecordDO> {
/**
* 创建分享记录
* @param createReqVO 创建信息
* @return 编号
*/
Long createRuleShareRecord(@Valid ScoreRuleShareRecordCreateReqVO createReqVO);
/**
* 获得分享记录详情
* @param reqVO
* @return 分享记录详情
*/
PageResult<ScoreRuleShareRecordDetailVO> getRuleShareRecordDetail(ScoreRuleShareRecordDetailReqVO reqVO);
/**
* 获得分享记录分页
* @param query 查询
* @return 分享记录分页
*/
PageResult<ScoreRuleShareRecordPageVO> getRuleShareRecordPage(ScoreRuleShareRecordQueryVO query);
}
package cn.iocoder.yudao.module.member.service.ScoreRuleShareRecord;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.dict.core.util.DictFrameworkUtils;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.service.AbstractService;
import cn.iocoder.yudao.module.member.dal.dataobject.ScoreRuleShareRecord.ScoreRuleShareRecordDO;
import cn.iocoder.yudao.module.member.dal.mysql.ScoreRuleShareRecord.ScoreRuleShareRecordMapper;
import cn.iocoder.yudao.module.member.util.ScoreRuleGenCodeUtils;
import cn.iocoder.yudao.module.member.vo.ScoreRuleShareRecord.*;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.util.List;
/**
* 分享记录 Service 实现类
*
* @author 系统管理员
*/
@Service
@Validated
public class ScoreRuleShareRecordServiceImpl extends AbstractService<ScoreRuleShareRecordMapper, ScoreRuleShareRecordDO> implements ScoreRuleShareRecordService {
@Resource
private ScoreRuleShareRecordMapper scoreRuleShareRecordMapper;
@Resource
private ScoreRuleGenCodeUtils scoreRuleGenCodeUtils;
@Override
public Long createRuleShareRecord(ScoreRuleShareRecordCreateReqVO createReqVO) {
// 校验是否已存在分享记录
Long count = scoreRuleShareRecordMapper.selectCount(new LambdaQueryWrapperX<ScoreRuleShareRecordDO>()
.eq(ScoreRuleShareRecordDO::getRuleId, createReqVO.getRuleId())
.eq(ScoreRuleShareRecordDO::getMemberId, createReqVO.getMemberId()));
if (count > 0) {
return null;
}
ScoreRuleShareRecordDO scoreRuleShareRecordDO = new ScoreRuleShareRecordDO();
scoreRuleShareRecordDO.setMemberId(createReqVO.getMemberId());
scoreRuleShareRecordDO.setRuleId(createReqVO.getRuleId());
scoreRuleShareRecordDO.setCode(scoreRuleGenCodeUtils.generateShareRecordCode());
// 插入
scoreRuleShareRecordMapper.insert(scoreRuleShareRecordDO);
// 返回
return scoreRuleShareRecordDO.getId();
}
@Override
public PageResult<ScoreRuleShareRecordDetailVO> getRuleShareRecordDetail(ScoreRuleShareRecordDetailReqVO reqVO) {
int size = reqVO.getRows();
int start = (reqVO.getPage() - 1) * size;
List<ScoreRuleShareRecordDetailVO> list = scoreRuleShareRecordMapper.getRuleShareRecordDetail(start, size, reqVO.getId());
if (list.isEmpty()) {
return PageResult.empty();
}
list.stream().forEach(item -> {
item.setTypeZh(DictFrameworkUtils.getDictDataFromCache("score_rule_type", item.getType().toString()).getLabel());
item.setTypeEn(DictFrameworkUtils.getDictDataFromCache("score_rule_type", item.getType().toString()).getLabelEn());
});
int total = scoreRuleShareRecordMapper.countScoreRuleShareRecordDetail(reqVO.getId());
return new PageResult<>(list, total, size, reqVO.getPage(), (total + size - 1) / size);
}
@Override
public PageResult<ScoreRuleShareRecordPageVO> getRuleShareRecordPage(ScoreRuleShareRecordQueryVO query) {
int size = query.getRows();
int start = (query.getPage() - 1) * size;
List<ScoreRuleShareRecordPageVO> list = scoreRuleShareRecordMapper.getScoreRuleShareRecordList(start, size, query);
if (list.isEmpty()) {
return PageResult.empty();
}
list.stream().forEach(item -> {
item.setTypeZh(DictFrameworkUtils.getDictDataFromCache("score_rule_type", item.getType().toString()).getLabel());
item.setTypeEn(DictFrameworkUtils.getDictDataFromCache("score_rule_type", item.getType().toString()).getLabelEn());
});
int total = scoreRuleShareRecordMapper.countScoreRuleShareRecord(query);
return new PageResult<>(list, total, size, query.getPage(), (total + size - 1) / size);
}
}
......@@ -15,12 +15,14 @@ import cn.iocoder.yudao.module.member.controller.app.scoreRule.vo.AppScoreRuleLi
import cn.iocoder.yudao.module.member.controller.app.scoreRule.vo.AppScoreRuleListReqVO;
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.dataobject.user.MemberUserDO;
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;
import cn.iocoder.yudao.module.member.enums.YesOrNoTypeEnum;
import cn.iocoder.yudao.module.member.service.user.MemberUserService;
import cn.iocoder.yudao.module.member.util.ScoreRuleGenCodeUtils;
import cn.iocoder.yudao.module.member.vo.scoreRule.*;
import cn.iocoder.yudao.module.member.vo.scoreRule.extra.ScoreRuleOrderVExtraVO;
......@@ -33,6 +35,7 @@ import org.apache.commons.collections4.ListUtils;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
......@@ -52,7 +55,10 @@ import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.*;
@Service
@Validated
public class ScoreRuleServiceImpl extends AbstractService<ScoreRuleMapper, ScoreRuleDO> implements ScoreRuleService {
private static final String PROD_REGISTER_URL = "https://app2.groupage.cn/#/pages/register/register?code=";
private static final String UAT_REGISTER_URL = "https://apptest.groupage.cn/#/pages/register/register?code=";
@Value("${spring.profiles.active}")
private String env;
@Resource
private ScoreRuleMapper scoreRuleMapper;
@Resource
......@@ -63,6 +69,8 @@ public class ScoreRuleServiceImpl extends AbstractService<ScoreRuleMapper, Score
private AdminUserApi adminUserApi;
@Resource
private ScoreRuleGenCodeUtils scoreRuleGenCodeUtils;
@Resource
private MemberUserService memberUserService;
@Override
public Long createScoreRule(ScoreRuleCreateReqVO createReqVO) {
......@@ -515,6 +523,12 @@ public class ScoreRuleServiceImpl extends AbstractService<ScoreRuleMapper, Score
if (scoreRuleDO.getType() == ScoreRuleTypeEnum.RECOMMEND.getValue()) {
ScoreRulerRecommendExtraVO scoreRulerRecommendExtraVO = JsonUtils.parseObject(scoreRuleDO.getExtra(), ScoreRulerRecommendExtraVO.class);
appScoreRuleListBackVO.setExtraRecommend(scoreRulerRecommendExtraVO);
MemberUserDO memberUserDO = memberUserService.getUser(reqVO.getMemberId());
if (memberUserDO != null && !"pro".equals(env)) {
appScoreRuleListBackVO.setRecommendUrl(UAT_REGISTER_URL + memberUserDO.getCode());
} else if (memberUserDO != null) {
appScoreRuleListBackVO.setRecommendUrl(PROD_REGISTER_URL + memberUserDO.getCode());
}
} else if (scoreRuleDO.getType() == ScoreRuleTypeEnum.SHARE.getValue()) {
ScoreRuleShareExtraVO scoreRuleShareExtraVO = JsonUtils.parseObject(scoreRuleDO.getExtra(), ScoreRuleShareExtraVO.class);
appScoreRuleListBackVO.setExtraShare(scoreRuleShareExtraVO);
......
......@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.member.util;
import cn.iocoder.yudao.framework.redis.helper.RedisHelper;
import cn.iocoder.yudao.module.member.dal.dataobject.scoreRule.ScoreRuleDO;
import cn.iocoder.yudao.module.member.dal.mysql.ScoreRuleShareRecord.ScoreRuleShareRecordMapper;
import cn.iocoder.yudao.module.member.dal.mysql.scoreRule.ScoreRuleMapper;
import com.alibaba.excel.util.DateUtils;
import org.redisson.api.RLock;
......@@ -28,6 +29,8 @@ public class ScoreRuleGenCodeUtils {
private RedissonClient redissonClient;
@Resource
private ScoreRuleMapper scoreRuleMapper;
@Resource
private ScoreRuleShareRecordMapper scoreRuleShareRecordMapper;
/**
* 生成积分规则编号
......@@ -65,6 +68,42 @@ public class ScoreRuleGenCodeUtils {
code.append(String.format("%05d", codeNum));
return code.toString();
}
/**
* 生成分享记录编号
*/
public String generateShareRecordCode() {
// 编号规则:S+年份+月份+5位数,S240100005
String key = "shareRecord:max:number";
StringBuilder code = new StringBuilder();
code.append("S");
code.append(DateUtils.format(new Date(), "yyMM"));
Long codeNum;
if (redisHelper.hasKey(key)) {
codeNum = redisHelper.incrBy(key, 1);
} else {
RLock lock = redissonClient.getLock("next:shareRecord:code:lock");
try {
boolean lockSuccess = lock.tryLock(2, 2, TimeUnit.SECONDS);
if (!lockSuccess) {
throw exception(GET_LOCK_FAILED);
}
String currentMaxShareRecordCode = scoreRuleShareRecordMapper.getCurrentMaxShareRecordCode();
if (currentMaxShareRecordCode == null){
codeNum = 1L;
} else {
codeNum = Long.parseLong(currentMaxShareRecordCode.substring(3)) + 1;
}
redisHelper.set(key, String.valueOf(codeNum),10, TimeUnit.SECONDS);
} catch (InterruptedException e) {
throw exception(GET_LOCK_FAILED);
} finally {
lock.unlock();
}
}
// 获得5位序列号,不足位前面补0
code.append(String.format("%05d", codeNum));
return code.toString();
}
public void historyScoreRuleCodeFlush() {
long start = 1L;
redisHelper.delete("scoreRule:max:number");
......
package cn.iocoder.yudao.module.member.vo.ScoreRuleShareRecord;
import lombok.Data;
/**
* 分享记录 Base VO,提供给添加、修改、详细的子 VO 使用
* 如果子 VO 存在差异的字段,请不要添加到这里,影响 Swagger 文档生成
*/
@Data
public class ScoreRuleShareRecordBaseVO {
}
package cn.iocoder.yudao.module.member.vo.ScoreRuleShareRecord;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import javax.validation.constraints.NotNull;
@Data
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
@ApiModel("管理后台 - 分享记录创建 Request VO")
public class ScoreRuleShareRecordCreateReqVO extends ScoreRuleShareRecordBaseVO {
@ApiModelProperty(value = "会员id", required = true)
@NotNull(message = "会员id不能为空")
private Long memberId;
@ApiModelProperty(value = "积分规则id", required = true)
@NotNull(message = "积分规则id不能为空")
private Long ruleId;
}
package cn.iocoder.yudao.module.member.vo.ScoreRuleShareRecord;
import cn.iocoder.yudao.framework.mybatis.core.vo.PageVO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import javax.validation.constraints.NotNull;
@Data
@ApiModel("管理后台 - 分享记录详情查询 VO")
public class ScoreRuleShareRecordDetailReqVO extends PageVO {
@ApiModelProperty(value = "分享记录id")
@NotNull(message = "分享记录id不能为空")
private Long id;
}
package cn.iocoder.yudao.module.member.vo.ScoreRuleShareRecord;
import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
/**
* 分享记录 Response VO
* @author 系统管理员
*/
@Data
@ApiModel("管理后台 - 分享记录详情 Response VO")
public class ScoreRuleShareRecordDetailVO {
@ExcelProperty("主键")
@ApiModelProperty(value = "主键", required = true)
private Long id;
@ApiModelProperty(value = "分享编号", required = true)
private String code;
@ApiModelProperty(value = "操作人")
private String memberName;
@ApiModelProperty(value = "分类(3推荐,4分享)")
private Integer type;
@ApiModelProperty(value = "分类中文")
private String typeZh;
@ApiModelProperty(value = "分类英文")
private String typeEn;
@ApiModelProperty(value = "积分规则标题中文")
private String titleZh;
@ApiModelProperty(value = "积分规则标题英文")
private String titleEn;
@ApiModelProperty(value = "单次积分")
private Integer score;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "操作时间")
private Date createTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "点击时间")
private Date triggerTime;
}
package cn.iocoder.yudao.module.member.vo.ScoreRuleShareRecord;
import lombok.*;
import java.util.*;
import io.swagger.annotations.*;
import com.alibaba.excel.annotation.ExcelProperty;
import org.springframework.format.annotation.DateTimeFormat;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
/**
* 分享记录 Response VO
* @author 系统管理员
*/
@Data
@ApiModel("管理后台 - 分享记录分页 Response VO")
public class ScoreRuleShareRecordPageVO {
@ExcelProperty("主键")
@ApiModelProperty(value = "主键", required = true)
private Long id;
@ApiModelProperty(value = "分享编号", required = true)
private String code;
@ApiModelProperty(value = "操作人")
private String memberName;
@ApiModelProperty(value = "分类(3推荐,4分享)")
private Integer type;
@ApiModelProperty(value = "分类中文")
private String typeZh;
@ApiModelProperty(value = "分类英文")
private String typeEn;
@ApiModelProperty(value = "积分规则标题中文")
private String titleZh;
@ApiModelProperty(value = "积分规则标题英文")
private String titleEn;
@ApiModelProperty(value = "有效次数")
private Integer triggerCount;
@ApiModelProperty(value = "总积分")
private Integer totalScore;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "操作时间")
private Date createTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "最后点击时间")
private Date lastTriggerTime;
}
package cn.iocoder.yudao.module.member.vo.ScoreRuleShareRecord;
import cn.iocoder.yudao.framework.mybatis.core.vo.PageVO;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
import org.springframework.format.annotation.DateTimeFormat;
import java.util.Date;
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
@Data
@ApiModel("管理后台 - 分享记录查询 VO")
public class ScoreRuleShareRecordQueryVO extends PageVO {
@ApiModelProperty(value = "操作人")
private String memberName;
@ApiModelProperty(value = "分类(3推荐,4分享)")
private Integer type;
@ApiModelProperty(value = "积分规则标题")
private String title;
@ApiModelProperty(value = "分享编号")
private String code;
@ApiModelProperty(value = "总积分查询条件操作符(1大于,2等于,3小于)")
private Integer relationSymbol;
@ApiModelProperty(value = "总积分")
private Integer totalScore;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "操作开始时间")
private Date beginCreateTime;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "操作结束时间")
private Date endCreateTime;
}
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="cn.iocoder.yudao.module.member.dal.mysql.ScoreRuleShareRecord.ScoreRuleShareRecordMapper">
<select id="getScoreRuleShareRecordList"
resultType="cn.iocoder.yudao.module.member.vo.ScoreRuleShareRecord.ScoreRuleShareRecordPageVO">
SELECT
srsr.id,
srsr.code,
srsr.create_time AS createTime,
srsr.total_score AS totalScore,
srsr.last_trigger_time AS lastTriggerTime,
mu.nickname AS memberName,
sr.type,
sr.title_zh AS titleZh,
sr.title_en AS titleEn,
(srsr.total_score / sr.get_score_once) AS triggerCount
FROM
score_rule_share_record srsr
LEFT JOIN member_user mu ON srsr.member_id = mu.id
LEFT JOIN score_rule sr ON srsr.rule_id = sr.id
WHERE 1 = 1 and srsr.deleted = 0
<include refid="shareRecordCondition"/>
order by srsr.create_time desc
limit #{start}, #{size}
</select>
<select id="countScoreRuleShareRecord" resultType="java.lang.Integer">
SELECT
count(*)
FROM
score_rule_share_record srsr
LEFT JOIN member_user mu ON srsr.member_id = mu.id
LEFT JOIN score_rule sr ON srsr.rule_id = sr.id
where 1 = 1 and srsr.deleted = 0
<include refid="shareRecordCondition"/>
</select>
<select id="getRuleShareRecordDetail"
resultType="cn.iocoder.yudao.module.member.vo.ScoreRuleShareRecord.ScoreRuleShareRecordDetailVO">
SELECT
srsr.id,
srsr.code,
srsr.create_time AS createTime,
msul.score_count AS score,
msul.create_time AS triggerTime,
mu.nickname AS memberName,
sr.type,
sr.title_zh AS titleZh,
sr.title_en AS titleEn
FROM
member_user_score_log msul
LEFT JOIN score_rule_share_record srsr ON msul.member_id = srsr.member_id AND msul.rule_id = srsr.rule_id
LEFT JOIN member_user mu ON srsr.member_id = mu.id
LEFT JOIN score_rule sr ON srsr.rule_id = sr.id
where srsr.deleted = 0 AND srsr.id = #{id}
order by srsr.create_time desc
limit #{start}, #{size}
</select>
<select id="countScoreRuleShareRecordDetail" resultType="java.lang.Integer">
SELECT
count(*)
FROM
member_user_score_log msul
LEFT JOIN score_rule_share_record srsr ON msul.member_id = srsr.member_id AND msul.rule_id = srsr.rule_id
where srsr.deleted = 0 AND srsr.id = #{id}
</select>
<select id="getCurrentMaxShareRecordCode" resultType="java.lang.String">
SELECT code FROM score_rule_share_record ORDER BY code desc LIMIT 1
</select>
<sql id="shareRecordCondition">
<if test="query.memberName != null and query.memberName != ''">
AND mu.nickname = #{query.memberName}
</if>
<if test="query.type != null">
AND sr.type = #{query.type}
</if>
<if test="query.title != null and query.title != ''">
AND ( sr.title_zh LIKE concat('%', #{query.title}, '%') OR sr.title_en LIKE concat('%', #{query.title}, '%') )
</if>
<if test="query.code != null and query.code != ''">
AND srsr.code = #{query.code}
</if>
<if test="query.beginCreateTime != null and query.endCreateTime != null">
AND ( srsr.create_time BETWEEN #{query.beginCreateTime} AND #{query.endCreateTime} )
</if>
<if test="query.relationSymbol != null and query.totalScore != null">
<!--1:大于 2:等于 3:小于-->
<if test="query.relationSymbol == 1">
AND srsr.total_score &gt; #{query.totalScore}
</if>
<if test="query.relationSymbol == 2">
AND srsr.total_score = #{query.totalScore}
</if>
<if test="query.relationSymbol == 3">
AND srsr.total_score &lt; #{query.totalScore}
</if>
</if>
</sql>
</mapper>
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