Commit 2f6092005b09aac72896f67adab6716aa2363083

Authored by owen
1 parent f99e2aec

member: 佣金解冻

yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java
@@ -13,6 +13,7 @@ public interface ErrorCodeConstants { @@ -13,6 +13,7 @@ public interface ErrorCodeConstants {
13 ErrorCode USER_NOT_EXISTS = new ErrorCode(1004001000, "用户不存在"); 13 ErrorCode USER_NOT_EXISTS = new ErrorCode(1004001000, "用户不存在");
14 ErrorCode USER_MOBILE_NOT_EXISTS = new ErrorCode(1004001001, "手机号未注册用户"); 14 ErrorCode USER_MOBILE_NOT_EXISTS = new ErrorCode(1004001001, "手机号未注册用户");
15 ErrorCode USER_MOBILE_USED = new ErrorCode(1004001002, "修改手机失败,该手机号({})已经被使用"); 15 ErrorCode USER_MOBILE_USED = new ErrorCode(1004001002, "修改手机失败,该手机号({})已经被使用");
  16 + ErrorCode MEMBER_FROZEN_BROKERAGE_PRICE_NOT_ENOUGH = new ErrorCode(1004001003, "用户冻结佣金({})数量不足");
16 17
17 // ========== AUTH 模块 1004003000 ========== 18 // ========== AUTH 模块 1004003000 ==========
18 ErrorCode AUTH_LOGIN_BAD_CREDENTIALS = new ErrorCode(1004003000, "登录失败,账号密码不正确"); 19 ErrorCode AUTH_LOGIN_BAD_CREDENTIALS = new ErrorCode(1004003000, "登录失败,账号密码不正确");
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/brokerage/record/MemberBrokerageRecordMapper.java
@@ -5,8 +5,12 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; @@ -5,8 +5,12 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
5 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; 5 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
6 import cn.iocoder.yudao.module.member.controller.admin.brokerage.record.vo.MemberBrokerageRecordPageReqVO; 6 import cn.iocoder.yudao.module.member.controller.admin.brokerage.record.vo.MemberBrokerageRecordPageReqVO;
7 import cn.iocoder.yudao.module.member.dal.dataobject.brokerage.record.MemberBrokerageRecordDO; 7 import cn.iocoder.yudao.module.member.dal.dataobject.brokerage.record.MemberBrokerageRecordDO;
  8 +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
8 import org.apache.ibatis.annotations.Mapper; 9 import org.apache.ibatis.annotations.Mapper;
9 10
  11 +import java.time.LocalDateTime;
  12 +import java.util.List;
  13 +
10 /** 14 /**
11 * 佣金记录 Mapper 15 * 佣金记录 Mapper
12 * 16 *
@@ -24,4 +28,15 @@ public interface MemberBrokerageRecordMapper extends BaseMapperX<MemberBrokerage @@ -24,4 +28,15 @@ public interface MemberBrokerageRecordMapper extends BaseMapperX<MemberBrokerage
24 .orderByDesc(MemberBrokerageRecordDO::getId)); 28 .orderByDesc(MemberBrokerageRecordDO::getId));
25 } 29 }
26 30
  31 + default List<MemberBrokerageRecordDO> selectListByStatusAndUnfreezeTimeLt(Integer status, LocalDateTime unfreezeTime) {
  32 + return selectList(new LambdaQueryWrapper<MemberBrokerageRecordDO>()
  33 + .eq(MemberBrokerageRecordDO::getStatus, status)
  34 + .lt(MemberBrokerageRecordDO::getUnfreezeTime, unfreezeTime));
  35 + }
  36 +
  37 + default int updateByIdAndStatus(Integer id, Integer status, MemberBrokerageRecordDO updateObj) {
  38 + return update(updateObj, new LambdaQueryWrapper<MemberBrokerageRecordDO>()
  39 + .eq(MemberBrokerageRecordDO::getId, id)
  40 + .eq(MemberBrokerageRecordDO::getStatus, status));
  41 + }
27 } 42 }
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/user/MemberUserMapper.java
@@ -92,4 +92,20 @@ public interface MemberUserMapper extends BaseMapperX&lt;MemberUserDO&gt; { @@ -92,4 +92,20 @@ public interface MemberUserMapper extends BaseMapperX&lt;MemberUserDO&gt; {
92 update(null, lambdaUpdateWrapper); 92 update(null, lambdaUpdateWrapper);
93 } 93 }
94 94
  95 + /**
  96 + * 更新用户冻结佣金(减少)
  97 + *
  98 + * @param id 用户编号
  99 + * @param incrCount 减少冻结佣金(负数)
  100 + * @return 更新条数
  101 + */
  102 + default int updateFrozenBrokeragePriceDecr(Long id, int incrCount) {
  103 + Assert.isTrue(incrCount < 0);
  104 + LambdaUpdateWrapper<MemberUserDO> lambdaUpdateWrapper = new LambdaUpdateWrapper<MemberUserDO>()
  105 + .setSql(" frozen_brokerage_price = frozen_brokerage_price + " + incrCount + // 负数,所以使用 + 号
  106 + ", brokerage_price = brokerage_price + " + -incrCount) // 负数,所以使用 - 号
  107 + .eq(MemberUserDO::getId, id)
  108 + .ge(MemberUserDO::getFrozenBrokeragePrice, -incrCount); // cas 逻辑
  109 + return update(null, lambdaUpdateWrapper);
  110 + }
95 } 111 }
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/job/brokerage/MemberBrokerageRecordUnfreezeJob.java 0 → 100644
  1 +package cn.iocoder.yudao.module.member.job.brokerage;
  2 +
  3 +import cn.hutool.core.util.StrUtil;
  4 +import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler;
  5 +import cn.iocoder.yudao.framework.tenant.core.job.TenantJob;
  6 +import cn.iocoder.yudao.module.member.service.brokerage.record.MemberBrokerageRecordService;
  7 +import org.springframework.stereotype.Component;
  8 +
  9 +import javax.annotation.Resource;
  10 +
  11 +/**
  12 + * 佣金解冻 Job
  13 + *
  14 + * @author owen
  15 + */
  16 +@Component
  17 +@TenantJob
  18 +public class MemberBrokerageRecordUnfreezeJob implements JobHandler {
  19 +
  20 + @Resource
  21 + private MemberBrokerageRecordService memberBrokerageRecordService;
  22 +
  23 + @Override
  24 + public String execute(String param) {
  25 + int count = memberBrokerageRecordService.unfreezeRecord();
  26 + return StrUtil.format("解冻佣金 {} 个", count);
  27 + }
  28 +
  29 +}
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/brokerage/record/MemberBrokerageRecordService.java
@@ -37,4 +37,12 @@ public interface MemberBrokerageRecordService { @@ -37,4 +37,12 @@ public interface MemberBrokerageRecordService {
37 * @param list 请求参数列表 37 * @param list 请求参数列表
38 */ 38 */
39 void addBrokerage(Long userId, List<BrokerageAddReqDTO> list); 39 void addBrokerage(Long userId, List<BrokerageAddReqDTO> list);
  40 +
  41 + /**
  42 + * 解冻佣金:将待结算的佣金记录,状态修改为已结算
  43 + *
  44 + * @return 解冻佣金的数量
  45 + */
  46 + int unfreezeRecord();
  47 +
40 } 48 }
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/brokerage/record/MemberBrokerageRecordServiceImpl.java
1 package cn.iocoder.yudao.module.member.service.brokerage.record; 1 package cn.iocoder.yudao.module.member.service.brokerage.record;
2 2
  3 +import cn.hutool.core.collection.CollUtil;
3 import cn.hutool.core.util.BooleanUtil; 4 import cn.hutool.core.util.BooleanUtil;
4 import cn.hutool.core.util.NumberUtil; 5 import cn.hutool.core.util.NumberUtil;
5 import cn.hutool.core.util.ObjectUtil; 6 import cn.hutool.core.util.ObjectUtil;
  7 +import cn.hutool.extra.spring.SpringUtil;
6 import cn.iocoder.yudao.framework.common.pojo.PageResult; 8 import cn.iocoder.yudao.framework.common.pojo.PageResult;
7 import cn.iocoder.yudao.module.member.api.brokerage.dto.BrokerageAddReqDTO; 9 import cn.iocoder.yudao.module.member.api.brokerage.dto.BrokerageAddReqDTO;
8 import cn.iocoder.yudao.module.member.controller.admin.brokerage.record.vo.MemberBrokerageRecordPageReqVO; 10 import cn.iocoder.yudao.module.member.controller.admin.brokerage.record.vo.MemberBrokerageRecordPageReqVO;
@@ -11,10 +13,12 @@ import cn.iocoder.yudao.module.member.dal.dataobject.brokerage.record.MemberBrok @@ -11,10 +13,12 @@ import cn.iocoder.yudao.module.member.dal.dataobject.brokerage.record.MemberBrok
11 import cn.iocoder.yudao.module.member.dal.dataobject.point.MemberPointConfigDO; 13 import cn.iocoder.yudao.module.member.dal.dataobject.point.MemberPointConfigDO;
12 import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; 14 import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
13 import cn.iocoder.yudao.module.member.dal.mysql.brokerage.record.MemberBrokerageRecordMapper; 15 import cn.iocoder.yudao.module.member.dal.mysql.brokerage.record.MemberBrokerageRecordMapper;
  16 +import cn.iocoder.yudao.module.member.enums.brokerage.BrokerageRecordStatusEnum;
14 import cn.iocoder.yudao.module.member.service.point.MemberPointConfigService; 17 import cn.iocoder.yudao.module.member.service.point.MemberPointConfigService;
15 import cn.iocoder.yudao.module.member.service.user.MemberUserService; 18 import cn.iocoder.yudao.module.member.service.user.MemberUserService;
16 import lombok.extern.slf4j.Slf4j; 19 import lombok.extern.slf4j.Slf4j;
17 import org.springframework.stereotype.Service; 20 import org.springframework.stereotype.Service;
  21 +import org.springframework.transaction.annotation.Transactional;
18 import org.springframework.validation.annotation.Validated; 22 import org.springframework.validation.annotation.Validated;
19 23
20 import javax.annotation.Resource; 24 import javax.annotation.Resource;
@@ -52,6 +56,7 @@ public class MemberBrokerageRecordServiceImpl implements MemberBrokerageRecordSe @@ -52,6 +56,7 @@ public class MemberBrokerageRecordServiceImpl implements MemberBrokerageRecordSe
52 } 56 }
53 57
54 @Override 58 @Override
  59 + @Transactional(rollbackFor = Exception.class)
55 public void addBrokerage(Long buyerId, List<BrokerageAddReqDTO> list) { 60 public void addBrokerage(Long buyerId, List<BrokerageAddReqDTO> list) {
56 MemberPointConfigDO memberConfig = memberConfigService.getPointConfig(); 61 MemberPointConfigDO memberConfig = memberConfigService.getPointConfig();
57 // 0 未启用分销功能 62 // 0 未启用分销功能
@@ -148,4 +153,56 @@ public class MemberBrokerageRecordServiceImpl implements MemberBrokerageRecordSe @@ -148,4 +153,56 @@ public class MemberBrokerageRecordServiceImpl implements MemberBrokerageRecordSe
148 } 153 }
149 } 154 }
150 155
  156 + @Override
  157 + public int unfreezeRecord() {
  158 + // 1. 查询待结算的佣金记录
  159 + List<MemberBrokerageRecordDO> records = memberBrokerageRecordMapper.selectListByStatusAndUnfreezeTimeLt(
  160 + BrokerageRecordStatusEnum.WAIT_SETTLEMENT.getStatus(), LocalDateTime.now());
  161 + if (CollUtil.isEmpty(records)) {
  162 + return 0;
  163 + }
  164 +
  165 + // 2. 遍历执行
  166 + int count = 0;
  167 + for (MemberBrokerageRecordDO record : records) {
  168 + try {
  169 + boolean successful = getSelf().unfreezeRecord(record);
  170 + if (successful) {
  171 + count++;
  172 + }
  173 + } catch (Exception e) {
  174 + log.error("[unfreezeRecord][record({}) 更新为已结算失败]", record.getId(), e);
  175 + }
  176 + }
  177 + return count;
  178 + }
  179 +
  180 + @Transactional(rollbackFor = Exception.class)
  181 + public boolean unfreezeRecord(MemberBrokerageRecordDO record) {
  182 + // 更新记录状态
  183 + MemberBrokerageRecordDO updateObj = new MemberBrokerageRecordDO()
  184 + .setStatus(BrokerageRecordStatusEnum.SETTLEMENT.getStatus())
  185 + .setUnfreezeTime(LocalDateTime.now());
  186 + int updateRows = memberBrokerageRecordMapper.updateByIdAndStatus(record.getId(), record.getStatus(), updateObj);
  187 + if (updateRows == 0) {
  188 + log.error("[unfreezeRecord][record({}) 更新为已结算失败]", record.getId());
  189 + return false;
  190 + }
  191 +
  192 + // 更新用户冻结佣金
  193 + memberUserService.updateUserFrozenBrokeragePrice(record.getUserId(), record.getPrice());
  194 +
  195 + log.info("[unfreezeRecord][record({}) 更新为已结算成功]", record.getId());
  196 + return true;
  197 + }
  198 +
  199 + /**
  200 + * 获得自身的代理对象,解决 AOP 生效问题
  201 + *
  202 + * @return 自己
  203 + */
  204 + private MemberBrokerageRecordServiceImpl getSelf() {
  205 + return SpringUtil.getBean(getClass());
  206 + }
  207 +
151 } 208 }
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java
@@ -176,7 +176,7 @@ public interface MemberUserService { @@ -176,7 +176,7 @@ public interface MemberUserService {
176 MemberUserDO getBrokerageUser(Long id); 176 MemberUserDO getBrokerageUser(Long id);
177 177
178 /** 178 /**
179 - * 增加用户佣金 179 + * 更新用户佣金
180 * 180 *
181 * @param id 用户编号 181 * @param id 用户编号
182 * @param brokeragePrice 用户可用佣金 182 * @param brokeragePrice 用户可用佣金
@@ -184,7 +184,7 @@ public interface MemberUserService { @@ -184,7 +184,7 @@ public interface MemberUserService {
184 void updateUserBrokeragePrice(Long id, int brokeragePrice); 184 void updateUserBrokeragePrice(Long id, int brokeragePrice);
185 185
186 /** 186 /**
187 - * 增加用户佣金 187 + * 更新用户冻结佣金
188 * 188 *
189 * @param id 用户编号 189 * @param id 用户编号
190 * @param frozenBrokeragePrice 用户冻结佣金 190 * @param frozenBrokeragePrice 用户冻结佣金
yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java
@@ -278,7 +278,14 @@ public class MemberUserServiceImpl implements MemberUserService { @@ -278,7 +278,14 @@ public class MemberUserServiceImpl implements MemberUserService {
278 @Override 278 @Override
279 @Transactional(rollbackFor = Exception.class) 279 @Transactional(rollbackFor = Exception.class)
280 public void updateUserFrozenBrokeragePrice(Long id, int frozenBrokeragePrice) { 280 public void updateUserFrozenBrokeragePrice(Long id, int frozenBrokeragePrice) {
281 - memberUserMapper.updateFrozenBrokeragePriceIncr(id, frozenBrokeragePrice); 281 + if (frozenBrokeragePrice > 0) {
  282 + memberUserMapper.updateFrozenBrokeragePriceIncr(id, frozenBrokeragePrice);
  283 + } else if (frozenBrokeragePrice < 0) {
  284 + int updateRows = memberUserMapper.updateFrozenBrokeragePriceDecr(id, frozenBrokeragePrice);
  285 + if (updateRows == 0) {
  286 + throw exception(MEMBER_FROZEN_BROKERAGE_PRICE_NOT_ENOUGH);
  287 + }
  288 + }
282 } 289 }
283 290
284 } 291 }