diff --git a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java b/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java index ba283ab0c..dc6439e74 100644 --- a/yudao-module-member/yudao-module-member-api/src/main/java/cn/iocoder/yudao/module/member/enums/ErrorCodeConstants.java +++ b/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 { ErrorCode USER_NOT_EXISTS = new ErrorCode(1004001000, "用户不存在"); ErrorCode USER_MOBILE_NOT_EXISTS = new ErrorCode(1004001001, "手机号未注册用户"); ErrorCode USER_MOBILE_USED = new ErrorCode(1004001002, "修改手机失败,该手机号({})已经被使用"); + ErrorCode MEMBER_FROZEN_BROKERAGE_PRICE_NOT_ENOUGH = new ErrorCode(1004001003, "用户冻结佣金({})数量不足"); // ========== AUTH 模块 1004003000 ========== ErrorCode AUTH_LOGIN_BAD_CREDENTIALS = new ErrorCode(1004003000, "登录失败,账号密码不正确"); diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/brokerage/record/MemberBrokerageRecordMapper.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/brokerage/record/MemberBrokerageRecordMapper.java index 52f85c1a1..fd3ce05fc 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/brokerage/record/MemberBrokerageRecordMapper.java +++ b/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; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.member.controller.admin.brokerage.record.vo.MemberBrokerageRecordPageReqVO; import cn.iocoder.yudao.module.member.dal.dataobject.brokerage.record.MemberBrokerageRecordDO; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import org.apache.ibatis.annotations.Mapper; +import java.time.LocalDateTime; +import java.util.List; + /** * 佣金记录 Mapper * @@ -24,4 +28,15 @@ public interface MemberBrokerageRecordMapper extends BaseMapperX selectListByStatusAndUnfreezeTimeLt(Integer status, LocalDateTime unfreezeTime) { + return selectList(new LambdaQueryWrapper() + .eq(MemberBrokerageRecordDO::getStatus, status) + .lt(MemberBrokerageRecordDO::getUnfreezeTime, unfreezeTime)); + } + + default int updateByIdAndStatus(Integer id, Integer status, MemberBrokerageRecordDO updateObj) { + return update(updateObj, new LambdaQueryWrapper() + .eq(MemberBrokerageRecordDO::getId, id) + .eq(MemberBrokerageRecordDO::getStatus, status)); + } } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/user/MemberUserMapper.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/user/MemberUserMapper.java index 39a7307c1..cafe10285 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/dal/mysql/user/MemberUserMapper.java +++ b/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 { update(null, lambdaUpdateWrapper); } + /** + * 更新用户冻结佣金(减少) + * + * @param id 用户编号 + * @param incrCount 减少冻结佣金(负数) + * @return 更新条数 + */ + default int updateFrozenBrokeragePriceDecr(Long id, int incrCount) { + Assert.isTrue(incrCount < 0); + LambdaUpdateWrapper lambdaUpdateWrapper = new LambdaUpdateWrapper() + .setSql(" frozen_brokerage_price = frozen_brokerage_price + " + incrCount + // 负数,所以使用 + 号 + ", brokerage_price = brokerage_price + " + -incrCount) // 负数,所以使用 - 号 + .eq(MemberUserDO::getId, id) + .ge(MemberUserDO::getFrozenBrokeragePrice, -incrCount); // cas 逻辑 + return update(null, lambdaUpdateWrapper); + } } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/job/brokerage/MemberBrokerageRecordUnfreezeJob.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/job/brokerage/MemberBrokerageRecordUnfreezeJob.java new file mode 100644 index 000000000..f4512cf08 --- /dev/null +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/job/brokerage/MemberBrokerageRecordUnfreezeJob.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.member.job.brokerage; + +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler; +import cn.iocoder.yudao.framework.tenant.core.job.TenantJob; +import cn.iocoder.yudao.module.member.service.brokerage.record.MemberBrokerageRecordService; +import org.springframework.stereotype.Component; + +import javax.annotation.Resource; + +/** + * 佣金解冻 Job + * + * @author owen + */ +@Component +@TenantJob +public class MemberBrokerageRecordUnfreezeJob implements JobHandler { + + @Resource + private MemberBrokerageRecordService memberBrokerageRecordService; + + @Override + public String execute(String param) { + int count = memberBrokerageRecordService.unfreezeRecord(); + return StrUtil.format("解冻佣金 {} 个", count); + } + +} diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/brokerage/record/MemberBrokerageRecordService.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/brokerage/record/MemberBrokerageRecordService.java index 16b82f78f..1d0f4e816 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/brokerage/record/MemberBrokerageRecordService.java +++ b/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 { * @param list 请求参数列表 */ void addBrokerage(Long userId, List list); + + /** + * 解冻佣金:将待结算的佣金记录,状态修改为已结算 + * + * @return 解冻佣金的数量 + */ + int unfreezeRecord(); + } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/brokerage/record/MemberBrokerageRecordServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/brokerage/record/MemberBrokerageRecordServiceImpl.java index 80c753fb5..58dc25af5 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/brokerage/record/MemberBrokerageRecordServiceImpl.java +++ b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/brokerage/record/MemberBrokerageRecordServiceImpl.java @@ -1,8 +1,10 @@ package cn.iocoder.yudao.module.member.service.brokerage.record; +import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.BooleanUtil; import cn.hutool.core.util.NumberUtil; import cn.hutool.core.util.ObjectUtil; +import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.member.api.brokerage.dto.BrokerageAddReqDTO; 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 import cn.iocoder.yudao.module.member.dal.dataobject.point.MemberPointConfigDO; import cn.iocoder.yudao.module.member.dal.dataobject.user.MemberUserDO; import cn.iocoder.yudao.module.member.dal.mysql.brokerage.record.MemberBrokerageRecordMapper; +import cn.iocoder.yudao.module.member.enums.brokerage.BrokerageRecordStatusEnum; import cn.iocoder.yudao.module.member.service.point.MemberPointConfigService; import cn.iocoder.yudao.module.member.service.user.MemberUserService; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; @@ -52,6 +56,7 @@ public class MemberBrokerageRecordServiceImpl implements MemberBrokerageRecordSe } @Override + @Transactional(rollbackFor = Exception.class) public void addBrokerage(Long buyerId, List list) { MemberPointConfigDO memberConfig = memberConfigService.getPointConfig(); // 0 未启用分销功能 @@ -148,4 +153,56 @@ public class MemberBrokerageRecordServiceImpl implements MemberBrokerageRecordSe } } + @Override + public int unfreezeRecord() { + // 1. 查询待结算的佣金记录 + List records = memberBrokerageRecordMapper.selectListByStatusAndUnfreezeTimeLt( + BrokerageRecordStatusEnum.WAIT_SETTLEMENT.getStatus(), LocalDateTime.now()); + if (CollUtil.isEmpty(records)) { + return 0; + } + + // 2. 遍历执行 + int count = 0; + for (MemberBrokerageRecordDO record : records) { + try { + boolean successful = getSelf().unfreezeRecord(record); + if (successful) { + count++; + } + } catch (Exception e) { + log.error("[unfreezeRecord][record({}) 更新为已结算失败]", record.getId(), e); + } + } + return count; + } + + @Transactional(rollbackFor = Exception.class) + public boolean unfreezeRecord(MemberBrokerageRecordDO record) { + // 更新记录状态 + MemberBrokerageRecordDO updateObj = new MemberBrokerageRecordDO() + .setStatus(BrokerageRecordStatusEnum.SETTLEMENT.getStatus()) + .setUnfreezeTime(LocalDateTime.now()); + int updateRows = memberBrokerageRecordMapper.updateByIdAndStatus(record.getId(), record.getStatus(), updateObj); + if (updateRows == 0) { + log.error("[unfreezeRecord][record({}) 更新为已结算失败]", record.getId()); + return false; + } + + // 更新用户冻结佣金 + memberUserService.updateUserFrozenBrokeragePrice(record.getUserId(), record.getPrice()); + + log.info("[unfreezeRecord][record({}) 更新为已结算成功]", record.getId()); + return true; + } + + /** + * 获得自身的代理对象,解决 AOP 生效问题 + * + * @return 自己 + */ + private MemberBrokerageRecordServiceImpl getSelf() { + return SpringUtil.getBean(getClass()); + } + } diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java index 206f9f1c7..380ad2c6c 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserService.java +++ b/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 { MemberUserDO getBrokerageUser(Long id); /** - * 增加用户佣金 + * 更新用户佣金 * * @param id 用户编号 * @param brokeragePrice 用户可用佣金 @@ -184,7 +184,7 @@ public interface MemberUserService { void updateUserBrokeragePrice(Long id, int brokeragePrice); /** - * 增加用户佣金 + * 更新用户冻结佣金 * * @param id 用户编号 * @param frozenBrokeragePrice 用户冻结佣金 diff --git a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java b/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java index db80661c6..0bd17facf 100644 --- a/yudao-module-member/yudao-module-member-biz/src/main/java/cn/iocoder/yudao/module/member/service/user/MemberUserServiceImpl.java +++ b/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 { @Override @Transactional(rollbackFor = Exception.class) public void updateUserFrozenBrokeragePrice(Long id, int frozenBrokeragePrice) { - memberUserMapper.updateFrozenBrokeragePriceIncr(id, frozenBrokeragePrice); + if (frozenBrokeragePrice > 0) { + memberUserMapper.updateFrozenBrokeragePriceIncr(id, frozenBrokeragePrice); + } else if (frozenBrokeragePrice < 0) { + int updateRows = memberUserMapper.updateFrozenBrokeragePriceDecr(id, frozenBrokeragePrice); + if (updateRows == 0) { + throw exception(MEMBER_FROZEN_BROKERAGE_PRICE_NOT_ENOUGH); + } + } } }