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 13 ErrorCode USER_NOT_EXISTS = new ErrorCode(1004001000, "用户不存在");
14 14 ErrorCode USER_MOBILE_NOT_EXISTS = new ErrorCode(1004001001, "手机号未注册用户");
15 15 ErrorCode USER_MOBILE_USED = new ErrorCode(1004001002, "修改手机失败,该手机号({})已经被使用");
  16 + ErrorCode MEMBER_FROZEN_BROKERAGE_PRICE_NOT_ENOUGH = new ErrorCode(1004001003, "用户冻结佣金({})数量不足");
16 17  
17 18 // ========== AUTH 模块 1004003000 ==========
18 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 5 import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
6 6 import cn.iocoder.yudao.module.member.controller.admin.brokerage.record.vo.MemberBrokerageRecordPageReqVO;
7 7 import cn.iocoder.yudao.module.member.dal.dataobject.brokerage.record.MemberBrokerageRecordDO;
  8 +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
8 9 import org.apache.ibatis.annotations.Mapper;
9 10  
  11 +import java.time.LocalDateTime;
  12 +import java.util.List;
  13 +
10 14 /**
11 15 * 佣金记录 Mapper
12 16 *
... ... @@ -24,4 +28,15 @@ public interface MemberBrokerageRecordMapper extends BaseMapperX<MemberBrokerage
24 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 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 37 * @param list 请求参数列表
38 38 */
39 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 1 package cn.iocoder.yudao.module.member.service.brokerage.record;
2 2  
  3 +import cn.hutool.core.collection.CollUtil;
3 4 import cn.hutool.core.util.BooleanUtil;
4 5 import cn.hutool.core.util.NumberUtil;
5 6 import cn.hutool.core.util.ObjectUtil;
  7 +import cn.hutool.extra.spring.SpringUtil;
6 8 import cn.iocoder.yudao.framework.common.pojo.PageResult;
7 9 import cn.iocoder.yudao.module.member.api.brokerage.dto.BrokerageAddReqDTO;
8 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 13 import cn.iocoder.yudao.module.member.dal.dataobject.point.MemberPointConfigDO;
12 14 import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO;
13 15 import cn.iocoder.yudao.module.member.dal.mysql.brokerage.record.MemberBrokerageRecordMapper;
  16 +import cn.iocoder.yudao.module.member.enums.brokerage.BrokerageRecordStatusEnum;
14 17 import cn.iocoder.yudao.module.member.service.point.MemberPointConfigService;
15 18 import cn.iocoder.yudao.module.member.service.user.MemberUserService;
16 19 import lombok.extern.slf4j.Slf4j;
17 20 import org.springframework.stereotype.Service;
  21 +import org.springframework.transaction.annotation.Transactional;
18 22 import org.springframework.validation.annotation.Validated;
19 23  
20 24 import javax.annotation.Resource;
... ... @@ -52,6 +56,7 @@ public class MemberBrokerageRecordServiceImpl implements MemberBrokerageRecordSe
52 56 }
53 57  
54 58 @Override
  59 + @Transactional(rollbackFor = Exception.class)
55 60 public void addBrokerage(Long buyerId, List<BrokerageAddReqDTO> list) {
56 61 MemberPointConfigDO memberConfig = memberConfigService.getPointConfig();
57 62 // 0 未启用分销功能
... ... @@ -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 176 MemberUserDO getBrokerageUser(Long id);
177 177  
178 178 /**
179   - * 增加用户佣金
  179 + * 更新用户佣金
180 180 *
181 181 * @param id 用户编号
182 182 * @param brokeragePrice 用户可用佣金
... ... @@ -184,7 +184,7 @@ public interface MemberUserService {
184 184 void updateUserBrokeragePrice(Long id, int brokeragePrice);
185 185  
186 186 /**
187   - * 增加用户佣金
  187 + * 更新用户冻结佣金
188 188 *
189 189 * @param id 用户编号
190 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 278 @Override
279 279 @Transactional(rollbackFor = Exception.class)
280 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 }
... ...