Browse Source

feat(job): 添加用户无违规奖励任务功能

- 新增 rewardNoViolationUsers 方法实现无违规用户奖励逻辑
- 添加 SecondUserCreditMapper 依赖注入用于积分操作
- 实现按天查询用户扣分记录并奖励无违规用户5分
- 防止重复发放奖励的逻辑检查
- 添加任务执行统计和日志记录
- 修复积分查询和更新相关代码逻辑
fcw 21 giờ trước cách đây
mục cha
commit
c97d399a7c

+ 149 - 0
alien-job/src/main/java/shop/alien/job/second/SecondUserCreditJob.java

@@ -5,9 +5,11 @@ import com.xxl.job.core.handler.annotation.XxlJob;
 import lombok.RequiredArgsConstructor;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.stereotype.Component;
+import shop.alien.entity.second.SecondUserCredit;
 import shop.alien.entity.second.SecondUserCreditDateRecord;
 import shop.alien.entity.second.SecondUserCreditRecord;
 import shop.alien.mapper.second.SecondUserCreditDateRecordMapper;
+import shop.alien.mapper.second.SecondUserCreditMapper;
 import shop.alien.mapper.second.SecondUserCreditRecordMapper;
 
 import java.util.*;
@@ -20,6 +22,7 @@ public class SecondUserCreditJob {
 
     private final SecondUserCreditRecordMapper secondUserCreditRecordMapper;
     private final SecondUserCreditDateRecordMapper secondUserCreditDateRecordMapper;
+    private final SecondUserCreditMapper secondUserCreditMapper;
 
     @XxlJob("sumUserCredit")
     public void sumUserCredit() {
@@ -199,4 +202,150 @@ public class SecondUserCreditJob {
         }
     }
 
+    @XxlJob("rewardNoViolationUsers")
+    public void rewardNoViolationUsers() {
+        log.info("开始执行无违规奖励任务");
+        // 查询用户当天有没有扣分,没有扣分就加5分
+        // 若今日无违规,奖励会在今日凌晨12:59:59发放
+
+        try {
+            // 获取当天的开始时间和结束时间
+            Calendar calendar = Calendar.getInstance();
+            calendar.set(Calendar.HOUR_OF_DAY, 0);
+            calendar.set(Calendar.MINUTE, 0);
+            calendar.set(Calendar.SECOND, 0);
+            calendar.set(Calendar.MILLISECOND, 0);
+            Date todayStart = calendar.getTime();
+
+            calendar.set(Calendar.HOUR_OF_DAY, 23);
+            calendar.set(Calendar.MINUTE, 59);
+            calendar.set(Calendar.SECOND, 59);
+            calendar.set(Calendar.MILLISECOND, 999);
+            Date todayEnd = calendar.getTime();
+
+            log.info("开始处理无违规奖励,日期范围:{} 至 {}", todayStart, todayEnd);
+
+            // 获取所有有积分记录的用户ID
+            LambdaQueryWrapper<SecondUserCreditRecord> userQuery = new LambdaQueryWrapper<>();
+            userQuery.select(SecondUserCreditRecord::getUserId)
+                    .eq(SecondUserCreditRecord::getDeleteFlag, 0)
+                    .groupBy(SecondUserCreditRecord::getUserId);
+            List<SecondUserCreditRecord> userRecords = secondUserCreditRecordMapper.selectList(userQuery);
+            Set<Integer> allUserIds = userRecords.stream()
+                    .map(SecondUserCreditRecord::getUserId)
+                    .collect(Collectors.toSet());
+
+            log.info("找到有积分记录的用户总数:{}", allUserIds.size());
+
+            int rewardCount = 0;
+            int skipCount = 0;
+            int failCount = 0;
+
+            // 为每个用户检查当天是否有扣分
+            for (Integer userId : allUserIds) {
+                try {
+                    // 查询用户当天是否有扣分记录(points < 0)
+                    LambdaQueryWrapper<SecondUserCreditRecord> deductionQuery = new LambdaQueryWrapper<>();
+                    deductionQuery.eq(SecondUserCreditRecord::getUserId, userId)
+                            .eq(SecondUserCreditRecord::getDeleteFlag, 0)
+                            .lt(SecondUserCreditRecord::getPoints, 0)  // 扣分记录(负数)
+                            .ge(SecondUserCreditRecord::getCreatedTime, todayStart)
+                            .le(SecondUserCreditRecord::getCreatedTime, todayEnd);
+                    long deductionCount = secondUserCreditRecordMapper.selectCount(deductionQuery);
+
+                    if (deductionCount > 0) {
+                        // 当天有扣分,跳过
+                        log.debug("用户 {} 当天有扣分记录,跳过奖励", userId);
+                        skipCount++;
+                        continue;
+                    }
+
+                    // 检查今天是否已经发放过奖励(避免重复发放)
+                    LambdaQueryWrapper<SecondUserCreditRecord> rewardQuery = new LambdaQueryWrapper<>();
+                    rewardQuery.eq(SecondUserCreditRecord::getUserId, userId)
+                            .eq(SecondUserCreditRecord::getDeleteFlag, 0)
+                            .eq(SecondUserCreditRecord::getPoints, 5)  // 奖励5分
+                            .eq(SecondUserCreditRecord::getPointsType, 10)  // 使用10作为无违规奖励类型
+                            .ge(SecondUserCreditRecord::getCreatedTime, todayStart)
+                            .le(SecondUserCreditRecord::getCreatedTime, todayEnd);
+                    long existingRewardCount = secondUserCreditRecordMapper.selectCount(rewardQuery);
+
+                    if (existingRewardCount > 0) {
+                        // 今天已经发放过奖励,跳过
+                        log.debug("用户 {} 今天已经发放过无违规奖励,跳过", userId);
+                        skipCount++;
+                        continue;
+                    }
+
+                    // 用户当天没有扣分,发放5分奖励
+                    // 1. 更新用户积分(使用累加方式)
+                    LambdaQueryWrapper<SecondUserCredit> creditQuery = new LambdaQueryWrapper<>();
+                    creditQuery.eq(SecondUserCredit::getUserId, userId)
+                            .eq(SecondUserCredit::getDeleteFlag, 0);
+                    SecondUserCredit userCredit = secondUserCreditMapper.selectOne(creditQuery);
+
+                    if (userCredit == null) {
+                        // 如果用户没有积分记录,先创建初始记录(0分)
+                        userCredit = new SecondUserCredit();
+                        userCredit.setUserId(userId);
+                        userCredit.setUserPoints(userCredit.getUserPoints() + 5);
+                        userCredit.setDeleteFlag(0);
+                        userCredit.setCreatedTime(new Date());
+                        userCredit.setUpdatedTime(new Date());
+                        secondUserCreditMapper.insert(userCredit);
+                    }
+                    
+                    // 2. 查询用户最新的一条积分记录,获取current_score_count(在更新积分之前查询)
+                    LambdaQueryWrapper<SecondUserCreditRecord> latestRecordQuery = new LambdaQueryWrapper<>();
+                    latestRecordQuery.eq(SecondUserCreditRecord::getUserId, userId)
+                            .eq(SecondUserCreditRecord::getDeleteFlag, 0)
+                            .orderByDesc(SecondUserCreditRecord::getCreatedTime)
+                            .last("LIMIT 1");
+                    SecondUserCreditRecord latestRecord = secondUserCreditRecordMapper.selectOne(latestRecordQuery);
+                    
+                    // 计算当前总积分:最新记录的current_score_count + 5分
+                    Integer currentScoreCount;
+                    if (latestRecord != null && latestRecord.getCurrentScoreCount() != null) {
+                        // 有历史记录,累加5分
+                        currentScoreCount = latestRecord.getCurrentScoreCount() + 5;
+                    } else {
+                        // 如果没有历史记录,从用户积分表中获取当前积分,然后加5
+                        if (userCredit != null && userCredit.getUserPoints() != null) {
+                            currentScoreCount = userCredit.getUserPoints() + 5;
+                        } else {
+                            currentScoreCount = 5;  // 默认值
+                        }
+                    }
+
+                    // 3. 使用累加方式更新积分
+                    secondUserCreditMapper.updatePointsByUserId(userId, 5);
+
+                    // 4. 创建积分记录
+                    SecondUserCreditRecord rewardRecord = new SecondUserCreditRecord();
+                    rewardRecord.setUserId(userId);
+                    rewardRecord.setPoints(5);
+                    rewardRecord.setPointsType(10);  // 10表示无违规奖励
+                    rewardRecord.setCurrentScoreCount(currentScoreCount);
+                    rewardRecord.setDeleteFlag(0);
+                    rewardRecord.setCreatedTime(new Date());
+                    rewardRecord.setUpdatedTime(new Date());
+                    secondUserCreditRecordMapper.insert(rewardRecord);
+
+                    rewardCount++;
+                    log.info("用户 {} 当天无违规,已发放5分奖励", userId);
+
+                } catch (Exception e) {
+                    log.error("处理用户无违规奖励失败,userId={}", userId, e);
+                    failCount++;
+                }
+            }
+
+            log.info("无违规奖励任务执行完成,奖励:{},跳过:{},失败:{}", rewardCount, skipCount, failCount);
+
+        } catch (Exception e) {
+            log.error("执行无违规奖励任务失败", e);
+            throw e;
+        }
+    }
+
 }

+ 6 - 3
alien-second/src/main/java/shop/alien/second/service/impl/SecondUserCreditRecordServiceImpl.java

@@ -76,7 +76,9 @@ public class SecondUserCreditRecordServiceImpl extends ServiceImpl<SecondUserCre
     public R<SecondUserCreditRecordListVo> getByUserId(Integer userId, Integer timeRange, Integer pointsType) {
         log.info("SecondUserCreditRecordServiceImpl.getByUserId, userId={}, timeRange={}, pointsType={}", userId, timeRange, pointsType);
         LambdaQueryWrapper<SecondUserCreditRecord> queryWrapper = new LambdaQueryWrapper<>();
+        LambdaQueryWrapper<SecondUserCreditRecord> recordsChangeQueryWrapper = new LambdaQueryWrapper<>();
         queryWrapper.eq(SecondUserCreditRecord::getUserId, userId);
+        recordsChangeQueryWrapper.eq(SecondUserCreditRecord::getUserId, userId);
 
         // 根据时间范围过滤
         Date startTime = null;
@@ -91,16 +93,17 @@ public class SecondUserCreditRecordServiceImpl extends ServiceImpl<SecondUserCre
         if (pointsType != null) {
             if (pointsType == 1) {
                 // 正分:points > 0
-                queryWrapper.gt(SecondUserCreditRecord::getPoints, 0);
+                recordsChangeQueryWrapper.gt(SecondUserCreditRecord::getPoints, 0);
             } else if (pointsType == 2) {
                 // 负分:points < 0
-                queryWrapper.lt(SecondUserCreditRecord::getPoints, 0);
+                recordsChangeQueryWrapper.lt(SecondUserCreditRecord::getPoints, 0);
             }
             // pointsType == 0 或 null 表示全部,不需要过滤
         }
 
+        recordsChangeQueryWrapper.orderByDesc(SecondUserCreditRecord::getCreatedTime);
         queryWrapper.orderByDesc(SecondUserCreditRecord::getCreatedTime);
-        List<SecondUserCreditRecord> recordsChange = this.list(queryWrapper);
+        List<SecondUserCreditRecord> recordsChange = this.list(recordsChangeQueryWrapper);
         
         // 查询日期积分记录,按照相同的时间范围筛选
         LambdaQueryWrapper<SecondUserCreditDateRecord> dateRecordQueryWrapper = new LambdaQueryWrapper<>();