积分:完善积分获得、退还、使用 相关逻辑

This commit is contained in:
owen
2023-09-23 14:11:16 +08:00
parent dc46dff62c
commit 052328c5fa
24 changed files with 383 additions and 87 deletions

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.member.api.point;
import cn.iocoder.yudao.module.member.api.point.dto.MemberPointConfigRespDTO;
import cn.iocoder.yudao.module.member.enums.point.MemberPointBizTypeEnum;
import javax.validation.constraints.Min;
@ -11,6 +12,13 @@ import javax.validation.constraints.Min;
*/
public interface MemberPointApi {
/**
* 获得积分配置
*
* @return 积分配置
*/
MemberPointConfigRespDTO getConfig();
/**
* 增加用户积分
*

View File

@ -0,0 +1,30 @@
package cn.iocoder.yudao.module.member.api.point.dto;
import lombok.Data;
/**
* 用户信息 Response DTO
*
* @author 芋道源码
*/
@Data
public class MemberPointConfigRespDTO {
/**
* 积分抵扣开关
*/
private Boolean tradeDeductEnable;
/**
* 积分抵扣,单位:分
* <p>
* 1 积分抵扣多少分
*/
private Integer tradeDeductUnitPrice;
/**
* 积分抵扣最大值
*/
private Integer tradeDeductMaxPrice;
/**
* 1 元赠送多少分
*/
private Integer tradeGivePoint;
}

View File

@ -33,5 +33,8 @@ public class MemberUserRespDTO {
* 手机
*/
private String mobile;
/**
* 积分
*/
private Integer point;
}

View File

@ -13,6 +13,7 @@ public interface ErrorCodeConstants {
ErrorCode USER_NOT_EXISTS = new ErrorCode(1004001000, "用户不存在");
ErrorCode USER_MOBILE_NOT_EXISTS = new ErrorCode(1004001001, "手机号未注册用户");
ErrorCode USER_MOBILE_USED = new ErrorCode(1004001002, "修改手机失败,该手机号({})已经被使用");
ErrorCode USER_POINT_NOT_ENOUGH = new ErrorCode(1004001003, "用户积分余额不足");
// ========== AUTH 模块 1004003000 ==========
ErrorCode AUTH_LOGIN_BAD_CREDENTIALS = new ErrorCode(1004003000, "登录失败,账号密码不正确");

View File

@ -18,8 +18,10 @@ public enum MemberPointBizTypeEnum implements IntArrayValuable {
SIGN(1, "签到", "签到获得 {} 积分", true),
ORDER_REWARD(10, "订单奖励", "下单获得 {} 积分", true),
ORDER_CANCEL(11, "订单取消", "退单获得 {} 积分", false), // 退回积分
ORDER_CANCEL(11, "订单取消", "订单取消,退还 {} 积分", true), // 退回积分
ORDER_USE(12, "订单使用", "下单使用 {} 积分", false), // 扣减积分
AFTER_SALE_REFUND_USED(13, "订单退款", "订单退款,退还 {} 积分", true), // 退回积分
AFTER_SALE_DEDUCT_GIVE(14, "订单退款", "订单退款,扣除赠送的 {} 积分", false), // 扣减积分
;
/**

View File

@ -1,6 +1,10 @@
package cn.iocoder.yudao.module.member.api.point;
import cn.hutool.core.lang.Assert;
import cn.iocoder.yudao.module.member.api.point.dto.MemberPointConfigRespDTO;
import cn.iocoder.yudao.module.member.convert.point.MemberPointConfigConvert;
import cn.iocoder.yudao.module.member.enums.point.MemberPointBizTypeEnum;
import cn.iocoder.yudao.module.member.service.point.MemberPointConfigService;
import cn.iocoder.yudao.module.member.service.point.MemberPointRecordService;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
@ -21,9 +25,17 @@ public class MemberPointApiImpl implements MemberPointApi {
@Resource
private MemberPointRecordService memberPointRecordService;
@Resource
private MemberPointConfigService memberPointConfigService;
@Override
public MemberPointConfigRespDTO getConfig() {
return MemberPointConfigConvert.INSTANCE.convert01(memberPointConfigService.getPointConfig());
}
@Override
public void addPoint(Long userId, Integer point, Integer bizType, String bizId) {
Assert.isTrue(point > 0);
MemberPointBizTypeEnum bizTypeEnum = MemberPointBizTypeEnum.getByType(bizType);
if (bizTypeEnum == null) {
throw exception(POINT_RECORD_BIZ_NOT_SUPPORT);
@ -33,11 +45,12 @@ public class MemberPointApiImpl implements MemberPointApi {
@Override
public void reducePoint(Long userId, Integer point, Integer bizType, String bizId) {
Assert.isTrue(point > 0);
MemberPointBizTypeEnum bizTypeEnum = MemberPointBizTypeEnum.getByType(bizType);
if (bizTypeEnum == null) {
throw exception(POINT_RECORD_BIZ_NOT_SUPPORT);
}
memberPointRecordService.createPointRecord(userId, point, bizTypeEnum, bizId);
memberPointRecordService.createPointRecord(userId, -point, bizTypeEnum, bizId);
}
}

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.member.convert.point;
import cn.iocoder.yudao.module.member.api.point.dto.MemberPointConfigRespDTO;
import cn.iocoder.yudao.module.member.controller.admin.point.vo.config.MemberPointConfigRespVO;
import cn.iocoder.yudao.module.member.controller.admin.point.vo.config.MemberPointConfigSaveReqVO;
import cn.iocoder.yudao.module.member.dal.dataobject.point.MemberPointConfigDO;
@ -20,4 +21,5 @@ public interface MemberPointConfigConvert {
MemberPointConfigDO convert(MemberPointConfigSaveReqVO bean);
MemberPointConfigRespDTO convert01(MemberPointConfigDO pointConfig);
}

View File

@ -1,12 +1,14 @@
package cn.iocoder.yudao.module.member.dal.mysql.user;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.member.controller.admin.user.vo.MemberUserPageReqVO;
import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import org.apache.ibatis.annotations.Mapper;
import java.util.List;
@ -62,4 +64,33 @@ public interface MemberUserMapper extends BaseMapperX<MemberUserDO> {
.apply("FIND_IN_SET({0}, tag_ids)", tagId));
}
/**
* 更新用户积分(增加)
*
* @param id 用户编号
* @param incrCount 增加积分(正数)
*/
default void updatePointIncr(Long id, Integer incrCount) {
Assert.isTrue(incrCount > 0);
LambdaUpdateWrapper<MemberUserDO> lambdaUpdateWrapper = new LambdaUpdateWrapper<MemberUserDO>()
.setSql(" point = point + " + incrCount)
.eq(MemberUserDO::getId, id);
update(null, lambdaUpdateWrapper);
}
/**
* 更新用户积分(减少)
*
* @param id 用户编号
* @param incrCount 增加积分(负数)
* @return 更新行数
*/
default int updatePointDecr(Long id, Integer incrCount) {
Assert.isTrue(incrCount < 0);
LambdaUpdateWrapper<MemberUserDO> lambdaUpdateWrapper = new LambdaUpdateWrapper<MemberUserDO>()
.setSql(" point = point + " + incrCount) // 负数,所以使用 + 号
.eq(MemberUserDO::getId, id);
return update(null, lambdaUpdateWrapper);
}
}

View File

@ -5,7 +5,6 @@ import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.module.member.controller.admin.point.vo.recrod.MemberPointRecordPageReqVO;
import cn.iocoder.yudao.module.member.dal.dataobject.point.MemberPointConfigDO;
import cn.iocoder.yudao.module.member.dal.dataobject.point.MemberPointRecordDO;
import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
import cn.iocoder.yudao.module.member.dal.mysql.point.MemberPointRecordMapper;
@ -14,6 +13,7 @@ import cn.iocoder.yudao.module.member.service.user.MemberUserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.validation.annotation.Validated;
@ -21,7 +21,9 @@ import javax.annotation.Resource;
import java.util.List;
import java.util.Set;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.module.member.enums.ErrorCodeConstants.USER_POINT_NOT_ENOUGH;
/**
@ -36,8 +38,6 @@ public class MemberPointRecordServiceImpl implements MemberPointRecordService {
@Resource
private MemberPointRecordMapper memberPointRecordMapper;
@Resource
private MemberPointConfigService memberPointConfigService;
@Resource
private MemberUserService memberUserService;
@ -64,32 +64,28 @@ public class MemberPointRecordServiceImpl implements MemberPointRecordService {
}
@Override
@Transactional(rollbackFor = Exception.class)
public void createPointRecord(Long userId, Integer point, MemberPointBizTypeEnum bizType, String bizId) {
MemberPointConfigDO pointConfig = memberPointConfigService.getPointConfig();
if (pointConfig == null || pointConfig.getTradeGivePoint() == null) {
log.error("[createPointRecord][增加积分失败tradeGivePoint 未配置userId({}) point({}) bizType({}) bizId({})]",
userId, point, bizType.getType(), bizId);
return;
}
// 1. 根据配置的比例,换算实际的积分
point = point * pointConfig.getTradeGivePoint();
if (!bizType.isAdd() && point > 0) {
point = -point;
}
// 2. 增加积分记录
// 1. 校验用户积分余额
MemberUserDO user = memberUserService.getUser(userId);
Integer userPoint = ObjectUtil.defaultIfNull(user.getPoint(), 0);
Integer totalPoint = userPoint + point; // 用户变动后的积分
int totalPoint = userPoint + point; // 用户变动后的积分
if (totalPoint < 0) {
throw exception(USER_POINT_NOT_ENOUGH);
}
// 2. 更新用户积分
boolean success = memberUserService.updateUserPoint(userId, point);
if (!success) {
throw exception(USER_POINT_NOT_ENOUGH);
}
// 3. 增加积分记录
MemberPointRecordDO record = new MemberPointRecordDO()
.setUserId(userId).setBizId(bizId).setBizType(bizType.getType())
.setTitle(bizType.getName()).setDescription(StrUtil.format(bizType.getDescription(), point))
.setPoint(point).setTotalPoint(totalPoint);
memberPointRecordMapper.insert(record);
// 3. 更新用户积分
memberUserService.updateUserPoint(userId, totalPoint);
}
}

View File

@ -164,6 +164,7 @@ public interface MemberUserService {
*
* @param userId 用户编号
* @param point 积分数量
* @return 更新结果
*/
void updateUserPoint(Long userId, Integer point);
boolean updateUserPoint(Long userId, Integer point);
}

View File

@ -260,8 +260,13 @@ public class MemberUserServiceImpl implements MemberUserService {
}
@Override
public void updateUserPoint(Long userId, Integer point) {
memberUserMapper.updateById(new MemberUserDO().setId(userId).setPoint(point));
public boolean updateUserPoint(Long id, Integer point) {
if (point > 0) {
memberUserMapper.updatePointIncr(id, point);
} else if (point < 0) {
return memberUserMapper.updatePointDecr(id, point) > 0;
}
return true;
}
}