Эх сурвалжийг харах

completeTaskByPriority方法代码优化

wangzhijun 6 өдөр өмнө
parent
commit
39ec5a82e6

+ 149 - 92
nightFragrance-massage/src/main/java/com/ylx/point/service/impl/PointUserActivityTaskCompletionServiceImpl.java

@@ -2,8 +2,10 @@ package com.ylx.point.service.impl;
 
 import cn.hutool.core.collection.CollectionUtil;
 import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.ObjUtil;
 import cn.hutool.core.util.ObjectUtil;
 import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.baomidou.mybatisplus.core.toolkit.Wrappers;
 import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
 import com.ylx.common.core.domain.model.WxLoginUser;
@@ -16,10 +18,7 @@ import com.ylx.point.domain.PointActivity;
 import com.ylx.point.domain.PointActivityTask;
 import com.ylx.point.domain.PointUserActivityTaskCompletion;
 import com.ylx.point.domain.vo.PointActivityOverviewVO;
-import com.ylx.point.enums.TaskNameEnum;
-import com.ylx.point.enums.PointActivityStatusEnum;
-import com.ylx.point.enums.PointActivityTaskTypeEnum;
-import com.ylx.point.enums.PointActivityTypeEnum;
+import com.ylx.point.enums.*;
 import com.ylx.point.enums.TaskNameEnum;
 import com.ylx.point.mapper.PointUserActivityTaskCompletionMapper;
 import com.ylx.point.service.IPointAccountService;
@@ -63,11 +62,7 @@ public class PointUserActivityTaskCompletionServiceImpl extends ServiceImpl<Poin
     /**
      * 活动类型优先级:新手活动 > 每日活动 > 每月活动
      */
-    private static final List<Integer> ACTIVITY_TYPE_PRIORITY = Arrays.asList(
-            PointActivityTypeEnum.NEW_USER_ACTIVITY.getCode(),
-            PointActivityTypeEnum.DAILY_ACTIVITY.getCode(),
-            PointActivityTypeEnum.MONTHLY_ACTIVITY.getCode()
-    );
+    private static final List<Integer> ACTIVITY_TYPE_PRIORITY = Arrays.asList(PointActivityTypeEnum.NEW_USER_ACTIVITY.getCode(), PointActivityTypeEnum.DAILY_ACTIVITY.getCode(), PointActivityTypeEnum.MONTHLY_ACTIVITY.getCode());
 
     @Override
     public PointActivityOverviewVO getPointActivityOverviewByActivityId(Long activityId) {
@@ -92,13 +87,7 @@ public class PointUserActivityTaskCompletionServiceImpl extends ServiceImpl<Poin
      */
     @Override
     public boolean isTodayCompleted(String openId, Long activityId, Long taskId, Integer taskType) {
-        return pointUserActivityTaskCompletionMapper.exists(Wrappers.lambdaQuery(PointUserActivityTaskCompletion.class)
-                .eq(PointUserActivityTaskCompletion::getOpenId, openId)
-                .eq(PointUserActivityTaskCompletion::getActivityId, activityId)
-                .eq(PointUserActivityTaskCompletion::getTaskId, taskId)
-                .eq(PointUserActivityTaskCompletion::getTaskType, taskType)
-                .eq(PointUserActivityTaskCompletion::getCompletedDate, LocalDate.now())
-        );
+        return pointUserActivityTaskCompletionMapper.exists(Wrappers.lambdaQuery(PointUserActivityTaskCompletion.class).eq(PointUserActivityTaskCompletion::getOpenId, openId).eq(PointUserActivityTaskCompletion::getActivityId, activityId).eq(PointUserActivityTaskCompletion::getTaskId, taskId).eq(PointUserActivityTaskCompletion::getTaskType, taskType).eq(PointUserActivityTaskCompletion::getCompletedDate, LocalDate.now()));
     }
 
     @Override
@@ -183,8 +172,8 @@ public class PointUserActivityTaskCompletionServiceImpl extends ServiceImpl<Poin
         if (isVerified) {
             Date queryTime = getQueryStartTime(activity.getIsPermanent(), activity.getActivityType());
             // 防重复发奖:已达标则直接返回
-            PointUserActivityTaskCompletion record = this.getTaskRecord(openId, activityId, taskId, taskTypeEnum.getCode());
-            if (record != null && record.getCompletedCount() >= targetCount) {
+            PointUserActivityTaskCompletion record = this.getTaskRecordInPeriod(openId, activityId, taskId, taskTypeEnum.getCode(), queryTime);
+            if (ObjectUtil.isNotNull(record) && record.getCompletedCount() >= targetCount) {
                 throw new ServiceException("任务奖励已领取");
             }
 
@@ -263,111 +252,179 @@ public class PointUserActivityTaskCompletionServiceImpl extends ServiceImpl<Poin
     }
 
     /**
-     * 获取任务完成记录
+     * 查询当前周期内的任务记录
+     * 这里需要你修改 Mapper/DAO 层,支持按时间范围查询
      */
-    private PointUserActivityTaskCompletion getTaskRecord(String openId, Long activityId, Long taskId, Integer taskType) {
-        return this.getOne(Wrappers.lambdaQuery(PointUserActivityTaskCompletion.class)
-                .eq(PointUserActivityTaskCompletion::getOpenId, openId)
-                .eq(PointUserActivityTaskCompletion::getActivityId, activityId)
-                .eq(PointUserActivityTaskCompletion::getTaskId, taskId)
-                .eq(PointUserActivityTaskCompletion::getTaskType, taskType)
-        );
+    private PointUserActivityTaskCompletion getTaskRecordInPeriod(String openId, Long activityId, Long taskId, Integer taskTypeCode, Date startTime) {
+        // 构建查询条件
+        LambdaQueryWrapper<PointUserActivityTaskCompletion> wrapper = Wrappers.lambdaQuery(PointUserActivityTaskCompletion.class).eq(PointUserActivityTaskCompletion::getOpenId, openId).eq(PointUserActivityTaskCompletion::getActivityId, activityId).eq(PointUserActivityTaskCompletion::getTaskId, taskId).eq(PointUserActivityTaskCompletion::getTaskType, taskTypeCode);
+
+        // 核心:如果 startTime 不为空,则限制在该时间之后(即本周期内)
+        if (startTime != null) {
+            wrapper.ge(PointUserActivityTaskCompletion::getCreateTime, startTime);
+        }
+
+        return this.getOne(wrapper);
     }
 
     /**
      * 通用优先级任务完成方法
+     * 按活动类型优先级(新手 > 每日 > 每月)遍历匹配任务,完成首个合格任务后立即返回
      */
-    private void completeTaskByPriority(String openId, TaskNameEnum activityNameEnum,
-                                        PointActivityTaskTypeEnum taskTypeEnum,
-                                        Function<Date, Integer> countFunction) {
-        // 批量查询所有有效任务
+    private void completeTaskByPriority(String openId, TaskNameEnum activityNameEnum, PointActivityTaskTypeEnum taskTypeEnum, Function<Date, Integer> countFunction) {
+        // 1. 批量查询所有有效任务
         List<PointActivityTask> allTasks = pointActivityTaskService.list(Wrappers.lambdaQuery(PointActivityTask.class)
                 .eq(PointActivityTask::getTaskName, activityNameEnum.getInfo())
                 .eq(PointActivityTask::getStatus, 0)
-                .eq(PointActivityTask::getIsDeleted, 0)
-        );
+                .eq(PointActivityTask::getIsDeleted, 0));
         if (CollectionUtil.isEmpty(allTasks)) {
             return;
         }
 
-        // 批量查询关联活动,解决N+1查询
+        // 2. 批量查询关联活动,避免N+1查询
         Set<Long> activityIds = allTasks.stream().map(PointActivityTask::getActivityId).collect(Collectors.toSet());
-        List<PointActivity> activityList = pointActivityService.listByIds(activityIds);
-        Map<Long, PointActivity> activityMap = activityList.stream().collect(Collectors.toMap(PointActivity::getId, a -> a));
+        Map<Long, PointActivity> activityMap = pointActivityService.listByIds(activityIds).stream()
+                .collect(Collectors.toMap(PointActivity::getId, a -> a));
 
-        // 按优先级处理活动类型
+        // 3. 按优先级遍历活动类型
         for (Integer typeCode : ACTIVITY_TYPE_PRIORITY) {
-            // 过滤当前类型的有效任务
-            List<PointActivityTask> taskList = allTasks.stream()
-                    .filter(task -> {
-                        PointActivity activity = activityMap.get(task.getActivityId());
-                        return activity != null
-                                && Objects.equals(activity.getActivityType(), typeCode)
-                                && Objects.equals(activity.getStatus(), PointActivityStatusEnum.IN_PROGRESS.getCode());
-                    })
-                    .collect(Collectors.toList());
-
-            if (CollectionUtil.isEmpty(taskList)) {
+            List<PointActivityTask> filteredTasks = filterValidTasks(allTasks, activityMap, typeCode);
+            if (CollectionUtil.isEmpty(filteredTasks)) {
                 continue;
             }
 
-            // 执行任务
-            for (PointActivityTask task : taskList) {
-                try {
-                    PointActivity activity = activityMap.get(task.getActivityId());
-                    int targetCount = Integer.parseInt(task.getTriggerValue());
-                    Date queryTime = getQueryStartTime(activity.getIsPermanent(), typeCode);
-                    int completed = countFunction.apply(queryTime);
-
-                    if (completed < targetCount) {
-                        continue;
-                    }
-
-                    // 防重复领取
-                    PointUserActivityTaskCompletion record = getTaskRecord(openId, activity.getId(), task.getId(), taskTypeEnum.getCode());
-                    if (record != null && record.getCompletedCount() >= targetCount) {
-                        continue;
-                    }
-
-                    // 完成任务+发奖
-                    completeTask(openId, activity.getId(), task.getId(), taskTypeEnum.getCode());
-                    pointAccountService.addPoints(openId, task.getRewardPoints().intValue(),
-                            activity.getName(), null, activity.getId(), task.getId(),
-                            taskTypeEnum.getCode(), activityNameEnum.getInfo());
-                    return;
-                } catch (ServiceException e) {
-                    if (!e.getMessage().contains("已完成") && !e.getMessage().contains("已领取")) {
-                        throw e;
-                    }
-                    log.warn("任务处理异常:{}", e.getMessage());
+            // 4. 遍历当前类型的任务,尝试完成
+            for (PointActivityTask task : filteredTasks) {
+                PointActivity activity = activityMap.get(task.getActivityId());
+                if (tryCompleteSingleTask(openId, task, activity, typeCode, taskTypeEnum, activityNameEnum, countFunction)) {
+                    return; // 完成首个合格任务后立即返回
                 }
             }
         }
     }
 
+    /**
+     * 过滤指定活动类型下的有效任务(活动存在 + 类型匹配 + 进行中)
+     */
+    private List<PointActivityTask> filterValidTasks(List<PointActivityTask> allTasks, Map<Long, PointActivity> activityMap, Integer typeCode) {
+        return allTasks.stream().filter(task -> {
+            PointActivity activity = activityMap.get(task.getActivityId());
+            return activity != null
+                    && Objects.equals(activity.getActivityType(), typeCode)
+                    && Objects.equals(activity.getStatus(), PointActivityStatusEnum.IN_PROGRESS.getCode());
+        }).collect(Collectors.toList());
+    }
+
+    /**
+     * 尝试完成单个任务,返回是否成功完成
+     */
+    private boolean tryCompleteSingleTask(String openId, PointActivityTask task, PointActivity activity,
+                                          Integer typeCode, PointActivityTaskTypeEnum taskTypeEnum,
+                                          TaskNameEnum activityNameEnum, Function<Date, Integer> countFunction) {
+        try {
+            // 1. 解析频率限制
+            TaskLimitTimesEnum limitEnum = parseFrequencyLimit(task);
+            if (limitEnum == null) {
+                return false;
+            }
+
+            // 2. 校验业务数据是否达标
+            Date queryTime = getQueryStartTime(activity.getIsPermanent(), typeCode);
+            if (!isTaskTargetMet(task, taskTypeEnum, limitEnum.getTime(), countFunction, queryTime)) {
+                return false;
+            }
+
+            // 3. 防重复领取:利用 TaskLimitTimesEnum 策略模式校验
+            PointUserActivityTaskCompletion record = getTaskRecordInPeriod(openId, activity.getId(), task.getId(), taskTypeEnum.getCode(), queryTime);
+            int completedCount = (record != null) ? record.getCompletedCount() : 0;
+            if (!limitEnum.executeCheck(completedCount)) {
+                return false;
+            }
+
+            // 4. 完成任务 + 发放积分
+            completeTask(openId, activity.getId(), task.getId(), taskTypeEnum.getCode());
+            pointAccountService.addPoints(openId, task.getRewardPoints().intValue(), activity.getName(),
+                    null, activity.getId(), task.getId(), taskTypeEnum.getCode(), activityNameEnum.getInfo());
+            return true;
+        } catch (ServiceException e) {
+            if (!e.getMessage().contains("已完成") && !e.getMessage().contains("已领取")) {
+                throw e;
+            }
+            log.warn("任务处理异常:{}", e.getMessage());
+            return false;
+        }
+    }
+
+    /**
+     * 解析任务频率限制配置,返回null表示配置异常(调用方应跳过该任务)
+     */
+    private TaskLimitTimesEnum parseFrequencyLimit(PointActivityTask task) {
+        String frequencyLimitValue = task.getFrequencyLimitValue();
+        if (StrUtil.isBlank(frequencyLimitValue)) {
+            log.warn("任务未配置频率限制值,跳过: taskId={}", task.getId());
+            return null;
+        }
+        TaskLimitTimesEnum limitEnum = TaskLimitTimesEnum.getByValue(frequencyLimitValue);
+        if (limitEnum == null || limitEnum.getTime() == null || limitEnum.getTime() <= 0) {
+            log.warn("任务配置异常,跳过处理: taskId={}", task.getId());
+            return null;
+        }
+        return limitEnum;
+    }
+
+    /**
+     * 校验任务业务目标是否达成
+     * - 充值任务:实际充值金额 >= triggerValue 目标值
+     * - 完成订单:实际完成次数 >= 频率限制次数
+     */
+    private boolean isTaskTargetMet(PointActivityTask task, PointActivityTaskTypeEnum taskTypeEnum,
+                                    int targetCount, Function<Date, Integer> countFunction, Date queryTime) {
+        int actualCount = countFunction.apply(queryTime);
+
+        if (ObjUtil.equals(taskTypeEnum.getCode(), PointActivityTaskTypeEnum.RECHARGE_TASK.getCode())) {
+            // 充值任务:triggerValue 为目标金额
+            String targetValueStr = task.getTriggerValue();
+            if (StrUtil.isBlank(targetValueStr)) {
+                log.warn("任务未配置目标值,跳过: taskId={}", task.getId());
+                return false;
+            }
+            int targetValue;
+            try {
+                targetValue = Integer.parseInt(targetValueStr);
+            } catch (NumberFormatException e) {
+                log.warn("任务目标值格式错误,跳过: taskId={}, value={}", task.getId(), targetValueStr);
+                return false;
+            }
+            return actualCount >= targetValue;
+        } else if (ObjUtil.equals(taskTypeEnum.getCode(), PointActivityTaskTypeEnum.COMPLETE_ORDER.getCode())) {
+            // 完成订单:实际完成次数 >= 目标次数
+            return actualCount >= targetCount;
+        }
+
+        // 其他任务类型(分享、浏览等)默认视为已达标
+        return true;
+    }
+
     @Override
     @Transactional(rollbackFor = Exception.class)
     public void completeOrderTaskByPriority(String openId) {
-        completeTaskByPriority(openId, TaskNameEnum.COMPLETE_ORDER,
-                PointActivityTaskTypeEnum.COMPLETE_ORDER,
-                new Function<Date, Integer>() {
-                    @Override
-                    public Integer apply(Date queryTime) {
-                        return orderService.countCompletedOrders(openId, queryTime);
-                    }
-                });
+        completeTaskByPriority(openId, TaskNameEnum.COMPLETE_ORDER, PointActivityTaskTypeEnum.COMPLETE_ORDER, new Function<Date, Integer>() {
+            @Override
+            public Integer apply(Date queryTime) {
+                return orderService.countCompletedOrders(openId, queryTime);
+            }
+        });
     }
 
     @Override
     @Transactional(rollbackFor = Exception.class)
     public void completeRechargeTaskByPriority(String openId) {
-        completeTaskByPriority(openId, TaskNameEnum.RECHARGE_TASK,
-                PointActivityTaskTypeEnum.RECHARGE_TASK,
-                new Function<Date, Integer>() {
-                    @Override
-                    public Integer apply(Date queryTime) {
-                        return rechargeService.countSuccessRecharges(openId, queryTime);
-                    }
-                });
+        completeTaskByPriority(openId, TaskNameEnum.RECHARGE_TASK, PointActivityTaskTypeEnum.RECHARGE_TASK, new Function<Date, Integer>() {
+            @Override
+            public Integer apply(Date queryTime) {
+                int latestAmount = rechargeService.getLatestRechargeAmount(openId, queryTime);
+                return ObjectUtil.defaultIfNull(latestAmount, 0);
+            }
+        });
     }
 }