Commit c5bdf2c1 authored by Smile's avatar Smile Committed by wux

会员等级详情及会员定时任务

parent 97cd4723
......@@ -72,4 +72,5 @@ public interface ErrorCodeConstants {
ErrorCode USER_ADDRESS_FIELD_ERROR = new ErrorCode(1004008027, "user.address.field.error");
ErrorCode SCORE_RULE_CUSTOMERSIDE_ERROR = new ErrorCode(1004008028, "score.rule.customer.side.error");
ErrorCode LEVEL_RULE_NOT_EXISTS = new ErrorCode(1004008028, "level.rule.not.exists");
ErrorCode LEVEL_DETAILs_NOT_EXISTS = new ErrorCode(1004008028, "level.details.not.exists");
}
package cn.iocoder.yudao.module.member.controller.admin.levelDetails;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.security.core.LoginUser;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberUserLevelConfigDO;
import cn.iocoder.yudao.module.member.dal.dataobject.levelOperatLog.MemberUserLevelOperateLogDO;
import cn.iocoder.yudao.module.member.dal.dataobject.memberUserLevelDetail.MemberUserLevelDetailsDO;
import cn.iocoder.yudao.module.member.dal.mysql.memberUserLevel.MemberUserLevelConfigMapper;
import cn.iocoder.yudao.module.member.enums.ErrorCodeConstants;
import cn.iocoder.yudao.module.member.service.levelDetails.MemberUserLevelDetailsService;
import cn.iocoder.yudao.module.member.service.levelOperateLog.MemberUserLevelOperateLogService;
import cn.iocoder.yudao.module.member.vo.userLevelDetails.MemberUserLevelDetailsBackVO;
import cn.iocoder.yudao.module.member.vo.userLevelDetails.MemberUserLevelDetailsQueryVO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
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 java.util.Date;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.error;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@Validated
@RestController
@Api(tags = "管理后台 - 会员等级详情记录")
@RequestMapping("/member/level-details")
public class MemberUserLevelDetailsController {
@Resource
private MemberUserLevelDetailsService memberUserLevelDetailsService;
@Resource
private MemberUserLevelOperateLogService memberUserLevelOperateLogService;
@Resource
private MemberUserLevelConfigMapper memberUserLevelConfigMapper;
@PostMapping("/page")
@ApiOperation("获得等级详情分页")
//@PreAuthorize("@ss.hasPermission('member:user-level-log:query')")
public CommonResult<PageResult<MemberUserLevelDetailsBackVO>> page(@Valid @RequestBody MemberUserLevelDetailsQueryVO query) {
PageResult<MemberUserLevelDetailsBackVO> pageResult = memberUserLevelDetailsService.getPage(query);
return success(pageResult);
}
@PutMapping("/update")
@ApiOperation("更新等级详情")
public CommonResult<Boolean> update(@Valid @RequestBody MemberUserLevelDetailsQueryVO reqVO) {
Long id = reqVO.getId();
MemberUserLevelDetailsDO memberUserLevelDetailsDO = memberUserLevelDetailsService.getById(id);
if (memberUserLevelDetailsDO == null) {
return error(ErrorCodeConstants.LEVEL_DETAILs_NOT_EXISTS);
}
LambdaQueryWrapper<MemberUserLevelConfigDO> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(MemberUserLevelConfigDO::getLevel, reqVO.getLevel());
// 执行查询
MemberUserLevelConfigDO configDO = memberUserLevelConfigMapper.selectOne(wrapper);
if (configDO==null){
return error(ErrorCodeConstants.LEVEL_RULE_NOT_EXISTS);
}
LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
memberUserLevelDetailsDO.setLevel(reqVO.getLevel());
memberUserLevelDetailsDO.setValidityPeriod(configDO.getValidityPeriod());
memberUserLevelDetailsDO.setSpecificSettings(reqVO.getSpecificSettings());
memberUserLevelDetailsDO.setRemarks(reqVO.getRemarks());
memberUserLevelDetailsDO.setConfigId(configDO.getId());
memberUserLevelDetailsDO.setUpdateTime(new Date());
memberUserLevelDetailsDO.setUpdater(String.valueOf(loginUser.getId()));
memberUserLevelDetailsService.updateById(memberUserLevelDetailsDO);
//添加操作日志
MemberUserLevelOperateLogDO memberUserLevelOperateLogDo = MemberUserLevelOperateLogDO.builder()
.configId(memberUserLevelDetailsDO.getConfigId())
.configName(configDO.getName())
.memberId(memberUserLevelDetailsDO.getMemberId())
.operator(loginUser.getNickname())
.remarks(memberUserLevelDetailsDO.getRemarks())
.level(memberUserLevelDetailsDO.getLevel())
.operateType(3)
.build();
memberUserLevelOperateLogService.save(memberUserLevelOperateLogDo);
return success(true);
}
}
package cn.iocoder.yudao.module.member.dal.dataobject.memberUserLevelDetail;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
/**
* @author Smile
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@TableName("member_user_level_details")
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
public class MemberUserLevelDetailsDO extends BaseDO {
/**
* 主键
*/
@TableId
private Long id;
private Long configId;
private Long memberId;
private Integer level;
private Integer validityPeriod;
private Boolean specificSettings;
private String remarks;
}
package cn.iocoder.yudao.module.member.dal.mysql.userLevelDetails;
import cn.iocoder.yudao.framework.mybatis.core.mapper.AbstractMapper;
import cn.iocoder.yudao.module.member.dal.dataobject.memberUserLevelDetail.MemberUserLevelDetailsDO;
import cn.iocoder.yudao.module.member.vo.userLevelDetails.MemberUserLevelDetailsBackVO;
import cn.iocoder.yudao.module.member.vo.userLevelDetails.MemberUserLevelDetailsQueryVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* 会员等级详情 Mapper
* @author Smile
*/
@Mapper
public interface MemberUserLevelDetailsMapper extends AbstractMapper<MemberUserLevelDetailsDO> {
List<MemberUserLevelDetailsBackVO> getPageDetailsList(@Param("start") int start, @Param("size") int size, @Param("query") MemberUserLevelDetailsQueryVO query);
int getPageCount(@Param("query") MemberUserLevelDetailsQueryVO query);
}
package cn.iocoder.yudao.module.member.job;
import cn.iocoder.yudao.framework.common.util.date.DateUtils;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQuery;
import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;
import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberUserLevelConfigDO;
import cn.iocoder.yudao.module.member.enums.MemberLevelStatusEnum;
import cn.iocoder.yudao.module.member.service.level.MemberUserLevelConfigService;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
/**
* 会员等级规则过期定时任务
* @author Smile
*/
@Component
@Slf4j
public class UserLevelConfigExpireTask implements JobHandler {
/**
* 会员等级规则的过期时间为每日的0点整
* 任务每天0点整运行,扫描当天0点过期的积分进行状态修改
* @param param 参数
* @return
* @throws Exception
*/
@Resource
private MemberUserLevelConfigService memberUserLevelConfigService;
@Override
public String execute(String param) throws Exception {
log.info("level config expire task running");
LambdaQuery<MemberUserLevelConfigDO> userLevelConfigDOLambdaQuery = new LambdaQuery<>();
userLevelConfigDOLambdaQuery.eq(MemberUserLevelConfigDO::getStatus, MemberLevelStatusEnum.ENABLED.getValue());
userLevelConfigDOLambdaQuery.le(MemberUserLevelConfigDO::getEndTime, DateUtils.getNextNDayStart(new Date(), 0));
List<MemberUserLevelConfigDO> todoList = memberUserLevelConfigService.selectList(userLevelConfigDOLambdaQuery);
log.info("level config expire task, to expire rule count :{}", todoList.size());
if (CollectionUtils.isEmpty(todoList)) {
return "success";
} else {
todoList.forEach(userLevelConfigDO -> {
userLevelConfigDO.setStatus(MemberLevelStatusEnum.EXPIRED.getValue());
memberUserLevelConfigService.updateById(userLevelConfigDO);
});
}
return "success";
}
}
package cn.iocoder.yudao.module.member.job;
import cn.iocoder.yudao.framework.common.util.date.DateUtils;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQuery;
import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;
import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberUserLevelConfigDO;
import cn.iocoder.yudao.module.member.dal.dataobject.score.MemberUserScoreDO;
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.redis.scoreRule.ScoreRuleRedisDao;
import cn.iocoder.yudao.module.member.enums.MemberLevelStatusEnum;
import cn.iocoder.yudao.module.member.enums.ScoreRuleStatusEnum;
import cn.iocoder.yudao.module.member.service.level.MemberUserLevelConfigService;
import cn.iocoder.yudao.module.member.service.score.MemberUserScoreService;
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.toolkit.CollectionUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
/**
* 会员等级详情定时任务
*/
@Component
@Slf4j
public class userLevelDetailsTask implements JobHandler {
/**
* 每天凌晨00:00AM和12:00AM 分别执行一次
* @param param 参数
* @return
* @throws Exception
*/
@Resource
private MemberUserLevelConfigService memberUserLevelConfigService;
@Resource
private MemberUserService userService;
@Resource
private MemberUserScoreLogService memberUserScoreLogService;
@Override
public String execute(String param) throws Exception {
log.info("level config expire task running");
LambdaQuery<MemberUserLevelConfigDO> userLevelConfigDoLambdaQuery = new LambdaQuery<>();
userLevelConfigDoLambdaQuery.eq(MemberUserLevelConfigDO::getStatus, MemberLevelStatusEnum.ENABLED.getValue());
List<MemberUserLevelConfigDO> todoList = memberUserLevelConfigService.selectList(userLevelConfigDoLambdaQuery);
log.info("level config expire task, to expire rule count :{}", todoList.size());
if (CollectionUtils.isEmpty(todoList)) {
return "success";
} else {
todoList.forEach(userLevelConfigDO -> {
LambdaQuery<MemberUserScoreLogDO> memberUserScoreLogDoLambdaQuery = new LambdaQuery<>();
//获取满足条件的所有用户
if (userLevelConfigDO.getStartDate()!=null){
memberUserScoreLogDoLambdaQuery.ge(MemberUserScoreLogDO::getCreateTime, userLevelConfigDO.getStartDate());
}else{
memberUserScoreLogDoLambdaQuery.ge(MemberUserScoreLogDO::getCreateTime, DateUtils.getNextNDayStart(new Date(), -(userLevelConfigDO.getAccumulationPeriod())));
}
});
}
return "success";
}
}
package cn.iocoder.yudao.module.member.service.levelDetails;
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.memberUserLevelDetail.MemberUserLevelDetailsDO;
import cn.iocoder.yudao.module.member.vo.userLevelDetails.MemberUserLevelDetailsBackVO;
import cn.iocoder.yudao.module.member.vo.userLevelDetails.MemberUserLevelDetailsQueryVO;
import javax.validation.Valid;
/**
* 会员等级详情 Service 接口
*
* @author Smile
*/
public interface MemberUserLevelDetailsService extends IService<MemberUserLevelDetailsDO> {
PageResult<MemberUserLevelDetailsBackVO> getPage(MemberUserLevelDetailsQueryVO query);
}
package cn.iocoder.yudao.module.member.service.levelDetails;
import cn.hutool.core.lang.generator.SnowflakeGenerator;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.service.AbstractService;
import cn.iocoder.yudao.module.member.dal.dataobject.level.MemberUserLevelConfigDO;
import cn.iocoder.yudao.module.member.dal.dataobject.memberUserLevelDetail.MemberUserLevelDetailsDO;
import cn.iocoder.yudao.module.member.dal.mysql.memberUserLevel.MemberUserLevelConfigMapper;
import cn.iocoder.yudao.module.member.dal.mysql.userLevelDetails.MemberUserLevelDetailsMapper;
import cn.iocoder.yudao.module.member.enums.ErrorCodeConstants;
import cn.iocoder.yudao.module.member.service.level.MemberUserLevelConfigService;
import cn.iocoder.yudao.module.member.vo.userLevelDetails.MemberUserLevelDetailsBackVO;
import cn.iocoder.yudao.module.member.vo.userLevelDetails.MemberUserLevelDetailsQueryVO;
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource;
import java.util.List;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.error;
/**
* 会员等级详情 Service 实现类
*
* @author Smile
*/
@Service
@Validated
public class MemberUserLevelDetailsServiceImpl extends AbstractService<MemberUserLevelDetailsMapper, MemberUserLevelDetailsDO> implements MemberUserLevelDetailsService {
@Resource
private MemberUserLevelDetailsMapper userLevelDetailsMapper;
@Resource
private AdminUserApi adminUserApi;
@Override
public PageResult<MemberUserLevelDetailsBackVO> getPage(MemberUserLevelDetailsQueryVO query) {
int start = (query.getPageNo() - 1) * query.getPageSize();
int size = query.getPageSize();
List<MemberUserLevelDetailsBackVO> list = userLevelDetailsMapper.getPageDetailsList(start, size, query);
list.stream().forEach(
item -> {
item.setUpdaterName(adminUserApi.getUser(Long.valueOf(item.getUpdater())).getNickname());
}
);
int total = userLevelDetailsMapper.getPageCount(query);
return new PageResult<>(list, total, query.getPageSize(), query.getPageNo(), (total + query.getPageSize() - 1) / query.getPageSize());
}
}
......@@ -25,6 +25,8 @@ public class MemberUserScoreLevelVO {
private Integer expiredScore;
@ApiModelProperty(value = "会员等级名称")
private String levelName;
@ApiModelProperty(value = "会员等级")
private Integer level;
@ApiModelProperty(value = "会员等级图标")
private String levelIcon;
}
package cn.iocoder.yudao.module.member.vo.userLevelDetails;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
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;
/**
* @author Smile
*/
@Data
@ApiModel("管理后台 - 会员等级详情 VO")
public class MemberUserLevelDetailsBackVO {
@ApiModelProperty(value = "详情id")
@JsonSerialize(using = ToStringSerializer.class)
private Long id;
@ApiModelProperty(value = "会员等级配置id")
private Long configId;
@ApiModelProperty(value = "会员等级配置编号")
private String ruleNumber;
@ApiModelProperty(value = "会员id")
private Long memberId;
@ApiModelProperty(value = "等级")
private Integer level;
@ApiModelProperty(value = "等级有效期")
private Integer validityPeriod;
@ApiModelProperty(value = "等级特殊设置")
private Boolean specificSettings;
@ApiModelProperty(value = "更新原因")
private String remarks;
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
@ApiModelProperty(value = "最后更新时间", required = true)
private Date updateTime;
@ApiModelProperty(value = "最后更新人")
private String updater;
@ApiModelProperty(value = "最后更新人名称")
private String updaterName;
}
package cn.iocoder.yudao.module.member.vo.userLevelDetails;
import io.swagger.annotations.ApiModelProperty;
import lombok.Builder;
import lombok.Data;
/**
* @author Smile
*/
@Data
@Builder
public class MemberUserLevelDetailsCreateReq {
@ApiModelProperty(value = "会员等级配置id")
private Long configId;
@ApiModelProperty(value = "会员id")
private Long memberId;
@ApiModelProperty(value = "等级")
private Integer level;
@ApiModelProperty(value = "等级有效期")
private Integer validityPeriod;
@ApiModelProperty(value = "等级特殊设置")
private Boolean specificSettings;
@ApiModelProperty(value = "更新原因")
private String remarks;
}
package cn.iocoder.yudao.module.member.vo.userLevelDetails;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Data;
/**
* @author Smile
*/
@Data
@ApiModel("管理后台 - 会员等级详情查询 VO")
public class MemberUserLevelDetailsQueryVO extends PageParam {
@ApiModelProperty(value = "id")
private Long id;
@ApiModelProperty(value = "会员id")
private Long memberId;
@ApiModelProperty(value = "会员等级配置id")
private Long configId;
@ApiModelProperty(value = "会员等级配置编号")
private String ruleNumber;
@ApiModelProperty(value = "等级")
private Integer level;
@ApiModelProperty(value = "等级有效期")
private Integer validityPeriod;
@ApiModelProperty(value = "等级特殊设置")
private Boolean specificSettings;
@ApiModelProperty(value = "更新原因")
private String remarks;
}
<?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.userLevelDetails.MemberUserLevelDetailsMapper">
<select id="getPageDetailsList"
resultType="cn.iocoder.yudao.module.member.vo.userLevelDetails.MemberUserLevelDetailsBackVO">
SELECT
muld.id as id,
muld.config_id as configId,
mulc.rule_number as ruleNumber ,
muld.member_id as memberId,
muld.updater as updater,
muld.remarks as remarks,
muld.update_time as updateTime ,
muld.`level` as level,
muld.validity_period as validityPeriod,
muld.specific_settings as specificSettings
FROM member_user_level_details muld
left join member_user_level_config mulc
on muld.config_id =mulc.id
where 1=1
and muld.member_id = #{query.memberId}
order by muld.create_time desc
limit #{start}, #{size}
</select>
<select id="getPageCount" resultType="java.lang.Integer">
select count(*)
FROM member_user_level_details muld
left join member_user_level_config mulc
on muld.config_id =mulc.id
where 1=1
and muld.member_id = #{query.memberId}
</select>
</mapper>
......@@ -1060,6 +1060,7 @@ redeem.cancel.status.error = \u5151\u6362\u4E2D\u72B6\u6001\u7684\u8BB0\u5F55\u6
level.bound.range.error = \u4E0A\u754C\u6570\u503C\u5FC5\u987B\u5927\u4E8E\u4E0B\u754C\u6570\u503C
level.bound.range.conflict = \u79EF\u5206\u8303\u56F4\u5B58\u5728\u51B2\u7A81
level.rule.not.exists = \u4F1A\u5458\u7B49\u7EA7\u89C4\u5219\u4E0D\u5B58\u5728
level.details.not.exists = \u4F1A\u5458\u7B49\u7EA7\u8BE6\u60C5\u4E0D\u5B58\u5728
score.operate.idempotent.error = \u5E42\u7B49key\u51B2\u7A81
score.rule.not.exists = \u79EF\u5206\u89C4\u5219\u4E0D\u5B58\u5728
......
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