src/main/java/cc/mrbird/febs/mall/mapper/MallMemberMapper.java
@@ -98,5 +98,7 @@ void updateVipLevelTimeAndLevel(@Param("id")Long id,@Param("vipLevelTime") Date lastLogin,@Param("level") String level); void updateLevel(@Param("id")Long id,@Param("level") String level); void updateNameAndAvatar(@Param("id")Long id, @Param("name")String name, @Param("photo")String photo); } src/main/java/cc/mrbird/febs/mall/mapper/MallMemberWalletMapper.java
@@ -4,6 +4,8 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper; import org.apache.ibatis.annotations.Param; import java.util.List; public interface MallMemberWalletMapper extends BaseMapper<MallMemberWallet> { MallMemberWallet selectWalletByMemberId(@Param("memberId") Long memberId); @@ -18,5 +20,5 @@ void updateBalanceWithId(@Param("record")MallMemberWallet mallMemberWallet); void updateScore(); void updateScore(@Param("list") List<Long> ids); } src/main/java/cc/mrbird/febs/mall/quartz/ProfitJob.java
@@ -17,15 +17,24 @@ /** * 每天凌晨 * 清空用户的碳积分 * 套餐过期后,更新用户为游客等级 */ @Scheduled(cron = "0 0 0 * * ?") @Scheduled(cron = "0 0 0/12 * * ?") public void updateMemberLevel() { memberProfitService.updateMemberLevel(); } /** * 每天凌晨 * 清空用户的碳积分 */ // @Scheduled(cron = "0 0 0 * * ?") @Scheduled(cron = "0 0 0/12 * * ?") public void updateMemberScore() { memberProfitService.updateMemberScore(); } /** * 每1小时执行一次 * 分发碳积分 * 根据会员等级分发 src/main/java/cc/mrbird/febs/mall/service/IMemberProfitService.java
@@ -45,4 +45,6 @@ void updateMemberLevel(); void updateRunScore(); void updateMemberScore(); } src/main/java/cc/mrbird/febs/mall/service/impl/MemberProfitServiceImpl.java
@@ -500,23 +500,39 @@ } } /** * 更新会员等级,将所有等级过期的会员等级重置为最低等级 * 查询 RunVip 表中按顺序号升序排列的第一条记录,获取最低会员等级。 * 构建查询条件,查询 MallMember 表中会员等级过期且当前等级不是最低等级的用户。 * 如果查询结果不为空,遍历每个用户,调用 updateLevel 方法将会员等级更新为最低等级。 * 处理完所有用户后,结束方法 */ @Override public void updateMemberLevel() { mallMemberWalletMapper.updateScore(); List<RunVip> runVips = runVipMapper.selectList(new LambdaQueryWrapper<RunVip>().orderByAsc(RunVip :: getOrderNumber)); RunVip runVip = runVips.get(0); //获取过期时间小于等于当前时间,并且会员等级不是最小等级游客的所有用户 LambdaQueryWrapper<MallMember> mallMemberLambdaQueryWrapper = new LambdaQueryWrapper<>(); mallMemberLambdaQueryWrapper.le(MallMember :: getVipLevelTime,DateUtil.date()); mallMemberLambdaQueryWrapper.ne(MallMember :: getLevel,runVip.getVipCode()); List<MallMember> mallMembers = mallMemberMapper.selectList(mallMemberLambdaQueryWrapper); if(CollUtil.isNotEmpty(mallMembers)){ mallMembers.forEach( item -> { mallMemberMapper.updateVipLevelTimeAndLevel(item.getId(),item.getVipLevelTime(),item.getLevel()); } ); // 更新会员等级的逻辑 try { List<RunVip> runVips = runVipMapper.selectList(new LambdaQueryWrapper<RunVip>().orderByAsc(RunVip::getOrderNumber)); RunVip runVip = runVips.get(0); // 获取过期时间小于等于当前时间,并且会员等级不是最小等级游客的所有用户 LambdaQueryWrapper<MallMember> mallMemberLambdaQueryWrapper = new LambdaQueryWrapper<>(); mallMemberLambdaQueryWrapper.le(MallMember::getVipLevelTime, DateUtil.date()); mallMemberLambdaQueryWrapper.ne(MallMember::getLevel, runVip.getVipCode()); List<MallMember> mallMembers = mallMemberMapper.selectList(mallMemberLambdaQueryWrapper); if (CollUtil.isNotEmpty(mallMembers)) { mallMembers.forEach( item -> { try { mallMemberMapper.updateLevel(item.getId(), runVip.getVipCode()); } catch (Exception e) { log.error("Error updating member level for user {}: ", item.getId(), e); } } ); } } catch (Exception e) { log.error("Error fetching or updating VIP levels: ", e); } } @@ -614,7 +630,46 @@ } } public boolean isDivisibleByTwo(int number) { return number % 2 == 0; } /** * 更新会员钱包中的积分,将所有积分大于0的会员钱包积分清零 * 初始化最大尝试次数 maxAttempts 和当前尝试次数 attemptCount。 * 使用 while 循环,每次查询1000条积分大于0的会员钱包记录。 * 如果查询结果为空,设置标志位 flag 为 false,退出循环。 * 否则,提取记录ID并调用 updateScore 方法将积分更新为0。 * 增加尝试次数,继续下一次循环,直到达到最大尝试次数或查询结果为空。 */ @Override public void updateMemberScore() { // 更新会员钱包积分的逻辑 int maxAttempts = 100; // 最大尝试次数 int attemptCount = 0; boolean flag = true; while (flag && attemptCount < maxAttempts) { try { Page<MallMemberWallet> page = new Page<>(0, 1000); IPage<MallMemberWallet> result = mallMemberWalletMapper.selectPage( page, new LambdaQueryWrapper<MallMemberWallet>() .gt(MallMemberWallet::getScore, 0) ); List<MallMemberWallet> mallMemberWallets = result.getRecords(); if (CollUtil.isEmpty(mallMemberWallets)) { flag = false; } else { List<Long> ids = mallMemberWallets.stream().map(MallMemberWallet::getId).collect(Collectors.toList()); mallMemberWalletMapper.updateScore(ids); } attemptCount++; } catch (Exception e) { log.error("Error updating member level: ", e); flag = false; // 发生异常时退出循环 } } } } src/main/java/cc/mrbird/febs/mall/service/impl/RunVipServiceImpl.java
@@ -304,10 +304,19 @@ ); if(CollUtil.isNotEmpty(mallMoneyFlows)){ BigDecimal reduce = mallMoneyFlows.stream().map(MallMoneyFlow::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add); if(reduce.intValue() >= realScore){ apiRunHealthVo.setScoreUsed(reduce.intValue() - realScore); apiRunHealthVo.setScoreTotal(reduce.intValue()); } apiRunHealthVo.setScoreTotal(reduce.intValue()); } List<MallMoneyFlow> mallMoneyFlowScoreOuts = mallMoneyFlowMapper.selectList( new LambdaQueryWrapper<MallMoneyFlow>() .eq(MallMoneyFlow::getMemberId, memberId) .eq(MallMoneyFlow::getFlowType, FlowTypeEnum.SCORE.getValue()) .eq(MallMoneyFlow::getType, RunVipMoneyFlowTypeEnum.SCORE_OUT_BALANCE.getValue()) .ge(MallMoneyFlow::getCreatedTime, DateUtil.beginOfDay(DateUtil.date())) .le(MallMoneyFlow::getCreatedTime, DateUtil.endOfDay(DateUtil.date())) ); if(CollUtil.isNotEmpty(mallMoneyFlowScoreOuts)){ BigDecimal reduce = mallMoneyFlowScoreOuts.stream().map(MallMoneyFlow::getAmount).reduce(BigDecimal.ZERO, BigDecimal::add).abs(); apiRunHealthVo.setScoreUsed(reduce.intValue()); } return apiRunHealthVo; } src/main/resources/mapper/modules/MallMemberMapper.xml
@@ -458,6 +458,12 @@ where id = #{id} </update> <update id="updateLevel"> update mall_member set level = #{level} where id = #{id} </update> <update id="updateNameAndAvatar"> update mall_member set avatar = #{photo}, src/main/resources/mapper/modules/MallMemberWalletMapper.xml
@@ -55,5 +55,9 @@ <update id="updateScore"> UPDATE mall_member_wallet SET score = 0 where id IN <foreach collection = "list" item = "item" separator="," open = "(" close = ")" > #{item} </foreach > </update> </mapper>