Răsfoiți Sursa

【feat】【v3】
1.优化代码逻辑

ChenYL 10 luni în urmă
părinte
comite
a49d086bd1

+ 2 - 1
doc/技术文档.md

@@ -607,8 +607,9 @@ ui设计工具:即时设计
 | task_name                           | varchar(128) | 任务名称                                                     |          |
 | description                         | varchar(300) | 任务描述                                                     |          |
 | points                              | int          | 奖励的积分(基本)                                           |          |
-| end_date                            | date         | 结束日期                                                     |          |
+| auto_archive_date                   | date         | 自动归档日期                                                 |          |
 | archive_status                      | varchar(10)  | 是否归档(活跃-ACTIVE,归档-ARCHIVE)                          |          |
+| manual_archive_date                 | date         | 手动归档日期                                                 |          |
 | display_order                       | int          | 显示顺序                                                     |          |
 | display_time                        | time         | 显示时间                                                     |          |
 | punch_in_method                     | varchar(10)  | 打卡方式(单次打卡-SINGLE,计数-COUNT、计时-TIMING)           |          |

+ 9 - 3
src/main/java/com/punchsettle/server/atomic/entity/PiTask.java

@@ -72,10 +72,10 @@ public class PiTask extends BaseEntity implements Serializable, ContinueTask {
     private Integer points;
 
     /**
-     * 结束日期
+     * 自动归档日期
      */
-    @Column(name = "end_date")
-    private LocalDate endDate;
+    @Column(name = "auto_archive_date")
+    private LocalDate autoArchiveDate;
 
     /**
      * 是否归档(活跃-ACTIVE,归档-ARCHIVE)
@@ -84,6 +84,12 @@ public class PiTask extends BaseEntity implements Serializable, ContinueTask {
     @Column(name = "archive_status")
     private ArchiveStatusEnum archiveStatus;
 
+    /**
+     * 手动归档日期
+     */
+    @Column(name = "manual_archive_date")
+    private LocalDate manualArchiveDate;
+
     /**
      * 显示顺序
      */

+ 2 - 2
src/main/java/com/punchsettle/server/atomic/service/impl/PiTaskServiceImpl.java

@@ -50,8 +50,8 @@ public class PiTaskServiceImpl implements IPiTaskService {
         if (!CollectionUtils.isEmpty(piTaskQuery.getIds())) {
             criteria.andIn(PiTask::getId, piTaskQuery.getIds());
         }
-        if (Objects.nonNull(piTaskQuery.getEndDateLt())) {
-            criteria.andLessThan(PiTask::getEndDate, piTaskQuery.getEndDateLt());
+        if (Objects.nonNull(piTaskQuery.getAutoArchiveDateLt())) {
+            criteria.andLessThan(PiTask::getAutoArchiveDate, piTaskQuery.getAutoArchiveDateLt());
         }
 
         weekend.excludeProperties(BaseEntity::getLastUpdatedBy,

+ 7 - 0
src/main/java/com/punchsettle/server/atomic/service/impl/SettleUserHistoryServiceImpl.java

@@ -7,6 +7,7 @@ import com.punchsettle.server.common.utils.Assert;
 import com.punchsettle.server.pojo.settle.SettleUserHistoryQuery;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
 import org.springframework.util.StringUtils;
 import tk.mybatis.mapper.weekend.Weekend;
 import tk.mybatis.mapper.weekend.WeekendCriteria;
@@ -50,6 +51,12 @@ public class SettleUserHistoryServiceImpl implements ISettleUserHistoryService {
         if (Objects.nonNull(query.getDistributeStatus())) {
             criteria.andEqualTo(SettleUserHistory::getDistributeStatus, query.getDistributeStatus());
         }
+        if (!CollectionUtils.isEmpty(query.getUserIds())) {
+            criteria.andIn(SettleUserHistory::getUserId, query.getUserIds());
+        }
+        if (!CollectionUtils.isEmpty(query.getSettleResults())) {
+            criteria.andIn(SettleUserHistory::getSettleResult, query.getSettleResults());
+        }
         return settleUserHistoryMapper.selectByExample(weekend);
     }
 

+ 1 - 1
src/main/java/com/punchsettle/server/constant/SettleResultEnum.java

@@ -15,7 +15,7 @@ public enum SettleResultEnum {
 
     SETTLE("已结算"),
     REVOKE_SETTLED("撤销结算"),
-    NOT_SETTLED("无需结算");
+    NO_SETTLED("无需结算");
 
     /**
      * 名称

+ 2 - 2
src/main/java/com/punchsettle/server/pojo/punchIn/PiTaskQuery.java

@@ -41,9 +41,9 @@ public class PiTaskQuery {
     private ArchiveStatusEnum archiveStatus;
 
     /**
-     * 结束日期(小于)
+     * 自动归档日期(小于)
      */
-    private LocalDate endDateLt;
+    private LocalDate autoArchiveDateLt;
 
     /**
      * 是否启用自动打卡(ENABLED-启用,DISABLED-关闭)

+ 2 - 2
src/main/java/com/punchsettle/server/pojo/punchIn/PiTaskRequest.java

@@ -54,9 +54,9 @@ public class PiTaskRequest {
     private Integer points;
 
     /**
-     * 结束日期
+     * 自动归档日期
      */
-    private LocalDate endDate;
+    private LocalDate autoArchiveDate;
 
     /**
      * 显示顺序

+ 14 - 0
src/main/java/com/punchsettle/server/pojo/settle/SettleUserHistoryQuery.java

@@ -1,8 +1,11 @@
 package com.punchsettle.server.pojo.settle;
 
 import com.punchsettle.server.constant.PointsDistributeStatusEnum;
+import com.punchsettle.server.constant.SettleResultEnum;
 import lombok.Data;
 
+import java.util.List;
+
 /**
  * @author tyuio
  * @version 1.0.0
@@ -17,6 +20,11 @@ public class SettleUserHistoryQuery {
      */
     private Long userId;
 
+    /**
+     * 用户ID列表
+     */
+    private List<Long> userIds;
+
     /**
      * 结算日期(右模糊)
      */
@@ -27,6 +35,12 @@ public class SettleUserHistoryQuery {
      */
     private String settleDate;
 
+    /**
+     * 结算状态
+     * @see SettleResultEnum
+     */
+    private List<SettleResultEnum> settleResults;
+
     /**
      * 积分下发状态
      * @see PointsDistributeStatusEnum

+ 8 - 6
src/main/java/com/punchsettle/server/service/manager/impl/PunchInCoreManagerImpl.java

@@ -49,12 +49,14 @@ public class PunchInCoreManagerImpl implements IPunchInCoreManager {
 
     @Override
     public boolean judgeRepeat(PiTask piTask, LocalDate repeatDate) {
-        // 存在结束日期,判断当前日期是否已归档
-        if (Objects.nonNull(piTask.getEndDate())) {
-            // 重复日期在归档日期之后
-            if (repeatDate.isAfter(piTask.getEndDate())) {
-                return false;
-            }
+        // 存在手动归档日期,重复日期在手动归档日期后,则不再重复
+        if (Objects.nonNull(piTask.getManualArchiveDate()) && repeatDate.isAfter(piTask.getManualArchiveDate())) {
+            return false;
+        }
+
+        // 存在自动归档日期,重复日期在自动归档日期后,则不再重复
+        if (Objects.nonNull(piTask.getAutoArchiveDate()) && repeatDate.isAfter(piTask.getAutoArchiveDate())) {
+            return false;
         }
 
         // 每天

+ 2 - 1
src/main/java/com/punchsettle/server/service/manager/impl/PunchInManagerImpl.java

@@ -324,7 +324,7 @@ public class PunchInManagerImpl implements IPunchInManager {
         if (CommonEnableStatusEnum.ENABLED.equals(request.getTaskPointsStatus()) && CollectionUtils.isEmpty(request.getContinueTaskExtList())) {
             throw BusinessException.fail("启用了任务积分计算,连续任务积分区间信息不能为空");
         }
-        if (Objects.nonNull(request.getEndDate()) && request.getEndDate().isBefore(today)) {
+        if (Objects.nonNull(request.getAutoArchiveDate()) && request.getAutoArchiveDate().isBefore(today)) {
             throw BusinessException.fail("任务自动归档时间无效,必需大于等于当前时间");
         }
 
@@ -496,6 +496,7 @@ public class PunchInManagerImpl implements IPunchInManager {
         // 归档
         PiTask addPiTask = copyAndArchivePiTask(id);
         addPiTask.setArchiveStatus(ArchiveStatusEnum.ARCHIVE);
+        addPiTask.setManualArchiveDate(LocalDate.now());
         piTaskService.insert(addPiTask);
 
         // 清楚缓存

+ 52 - 38
src/main/java/com/punchsettle/server/service/manager/impl/SettleManagerImpl.java

@@ -31,10 +31,6 @@ import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.CollectionUtils;
 
 import com.punchsettle.server.atomic.ContinueTask;
-import com.punchsettle.server.atomic.entity.PiMultiTask;
-import com.punchsettle.server.atomic.entity.PiMultiTaskExt;
-import com.punchsettle.server.atomic.entity.PiMultiTaskHistory;
-import com.punchsettle.server.atomic.entity.PiMultiTaskRela;
 import com.punchsettle.server.atomic.entity.PiStatus;
 import com.punchsettle.server.atomic.entity.PiTask;
 import com.punchsettle.server.atomic.entity.PiTaskExt;
@@ -59,9 +55,6 @@ import com.punchsettle.server.constant.ContinueStatusEnum;
 import com.punchsettle.server.constant.PunchInResultEnum;
 import com.punchsettle.server.constant.SettleResultEnum;
 import com.punchsettle.server.constant.VersionStatusEnum;
-import com.punchsettle.server.pojo.punchIn.PiMultiTaskExtQuery;
-import com.punchsettle.server.pojo.punchIn.PiMultiTaskHistoryQuery;
-import com.punchsettle.server.pojo.punchIn.PiMultiTaskQuery;
 import com.punchsettle.server.pojo.punchIn.PiStatusQuery;
 import com.punchsettle.server.pojo.punchIn.PiTaskData;
 import com.punchsettle.server.pojo.punchIn.PiTaskExtQuery;
@@ -174,7 +167,7 @@ public class SettleManagerImpl implements ISettleManager {
         Map<Long, List<SettleTaskRelaHistory>> settleTaskRelaHistoryMap = new HashMap<>();
 
         // 获取结算数据
-        List<SettleData> settleDataList = getSettleData(userIds, punchInDateStr);
+        List<SettleData> settleDataList = getSettleData(userIds, punchInDate);
 
         for (SettleData settleData : settleDataList) {
             // 新增结算用户记录
@@ -217,7 +210,7 @@ public class SettleManagerImpl implements ISettleManager {
                 // 有打卡任务,但是今天无需结算
                 boolean repeatResult = punchInCoreManager.judgeRepeat(piTask, punchInDate);
                 if (!repeatResult) {
-                    addSettleTaskRelaHistory.setSettleResult(SettleResultEnum.NOT_SETTLED);
+                    addSettleTaskRelaHistory.setSettleResult(SettleResultEnum.NO_SETTLED);
                     addSettleTaskRelaHistory.setSettlePoints(0);
                     addSettleTaskRelaHistories.add(addSettleTaskRelaHistory);
                     continue;
@@ -284,66 +277,87 @@ public class SettleManagerImpl implements ISettleManager {
      * 获取用户ID-打卡结算数据关联
      *
      * @param userIds 设计的用户
-     * @param punchInDateStr 打卡日期
+     * @param punchInDate 打卡日期
      * @return
      */
-    private List<SettleData> getSettleData(List<Long> userIds, String punchInDateStr) {
+    private List<SettleData> getSettleData(List<Long> userIds, LocalDate punchInDate) {
 
         // 获取多任务信息,用户ID-多任务关联
-        PiMultiTaskQuery piMultiTaskQuery = new PiMultiTaskQuery();
-        piMultiTaskQuery.setMultiTaskTaskStatus(VersionStatusEnum.ACTIVE);
-        piMultiTaskQuery.setUserIds(userIds);
-        List<PiMultiTask> piMultiTasks = piMultiTaskService.queryByCondition(piMultiTaskQuery);
-        Map<Long, PiMultiTask> piMultiTaskMap = piMultiTasks.stream()
-                .collect(Collectors.toMap(PiMultiTask::getUserId, Function.identity(), (key1, key2) -> key1));
+//        PiMultiTaskQuery piMultiTaskQuery = new PiMultiTaskQuery();
+//        piMultiTaskQuery.setMultiTaskTaskStatus(VersionStatusEnum.ACTIVE);
+//        piMultiTaskQuery.setUserIds(userIds);
+//        List<PiMultiTask> piMultiTasks = piMultiTaskService.queryByCondition(piMultiTaskQuery);
+//        Map<Long, PiMultiTask> piMultiTaskMap = piMultiTasks.stream()
+//                .collect(Collectors.toMap(PiMultiTask::getUserId, Function.identity(), (key1, key2) -> key1));
 
         // 多任务ID
-        Set<Long> multiTaskIds = piMultiTasks.stream().map(PiMultiTask::getId).collect(Collectors.toSet());
+//        Set<Long> multiTaskIds = piMultiTasks.stream().map(PiMultiTask::getId).collect(Collectors.toSet());
         // 多任务唯一ID
-        Set<Long> multiTaskUniqueIds = piMultiTasks.stream().map(PiMultiTask::getUniqueId).collect(Collectors.toSet());
+//        Set<Long> multiTaskUniqueIds = piMultiTasks.stream().map(PiMultiTask::getUniqueId).collect(Collectors.toSet());
 
         // 获取多任务拓展信息,多任务ID-多任务拓展关联
-        PiMultiTaskExtQuery piMultiTaskExtQuery = new PiMultiTaskExtQuery();
-        piMultiTaskExtQuery.setMultiTaskIds(multiTaskIds);
-        List<PiMultiTaskExt> piMultiTaskExtList = piMultiTaskExtService.queryByCondition(piMultiTaskExtQuery);
-        Map<Long, List<PiMultiTaskExt>> piMultiTaskExtMap =
-                piMultiTaskExtList.stream().collect(Collectors.groupingBy(PiMultiTaskExt::getMultiTaskId));
+//        PiMultiTaskExtQuery piMultiTaskExtQuery = new PiMultiTaskExtQuery();
+//        piMultiTaskExtQuery.setMultiTaskIds(multiTaskIds);
+//        List<PiMultiTaskExt> piMultiTaskExtList = piMultiTaskExtService.queryByCondition(piMultiTaskExtQuery);
+//        Map<Long, List<PiMultiTaskExt>> piMultiTaskExtMap =
+//                piMultiTaskExtList.stream().collect(Collectors.groupingBy(PiMultiTaskExt::getMultiTaskId));
 
         // 获取多任务打卡历史信息,多任务唯一ID-多任务打卡历史关联
-        PiMultiTaskHistoryQuery piMultiTaskHistoryQuery = new PiMultiTaskHistoryQuery();
-        piMultiTaskHistoryQuery.setPunchInMultiTaskUniqueIds(multiTaskUniqueIds);
-        piMultiTaskHistoryQuery.setPunchInDate(punchInDateStr);
-        List<PiMultiTaskHistory> piMultiTaskHistories =
-                piMultiTaskHistoryService.queryByCondition(piMultiTaskHistoryQuery);
-        Map<Long, PiMultiTaskHistory> piMultiTaskHistoryMap = piMultiTaskHistories.stream().collect(
-                Collectors.toMap(PiMultiTaskHistory::getMultiTaskUniqueId, Function.identity(), (key1, key2) -> key1));
+//        PiMultiTaskHistoryQuery piMultiTaskHistoryQuery = new PiMultiTaskHistoryQuery();
+//        piMultiTaskHistoryQuery.setPunchInMultiTaskUniqueIds(multiTaskUniqueIds);
+//        piMultiTaskHistoryQuery.setPunchInDate(punchInDateStr);
+//        List<PiMultiTaskHistory> piMultiTaskHistories =
+//                piMultiTaskHistoryService.queryByCondition(piMultiTaskHistoryQuery);
+//        Map<Long, PiMultiTaskHistory> piMultiTaskHistoryMap = piMultiTaskHistories.stream().collect(
+//                Collectors.toMap(PiMultiTaskHistory::getMultiTaskUniqueId, Function.identity(), (key1, key2) -> key1));
 
         // 打卡任务状态
         PiStatusQuery piStatusQuery = new PiStatusQuery();
         piStatusQuery.setUserIds(userIds);
         List<PiStatus> piStatusList = piStatusService.queryByCondition(piStatusQuery);
         // 打卡任务状态,多任务唯一ID-打卡状态关联
-        Map<Long, PiStatus> piStatusMapInMultiTask = piStatusList.stream().filter(v -> Objects.nonNull(v.getMultiTaskUniqueId())).collect(Collectors.toMap(PiStatus::getMultiTaskUniqueId, Function.identity(), (key1, key2) -> key1));
+//        Map<Long, PiStatus> piStatusMapInMultiTask = piStatusList.stream().filter(v -> Objects.nonNull(v.getMultiTaskUniqueId())).collect(Collectors.toMap(PiStatus::getMultiTaskUniqueId, Function.identity(), (key1, key2) -> key1));
         // 打卡任务状态,任务唯一ID-打卡状态关联
         Map<Long, PiStatus> piStatusMapInTask = piStatusList.stream().filter(v -> Objects.nonNull(v.getTaskUniqueId())).collect(Collectors.toMap(PiStatus::getTaskUniqueId, Function.identity(), (key1, key2) -> key1));
 
         // 多任务关联打卡任务,多任务ID-多任务关联打卡任务关联
-        List<PiMultiTaskRela> piMultiTaskRelaList = piMultiTaskRelaService.queryByMultiTaskId(multiTaskIds);
-        Map<Long, List<PiMultiTaskRela>> piMultiTaskRelaMap =
-                piMultiTaskRelaList.stream().collect(Collectors.groupingBy(PiMultiTaskRela::getMultiTaskId));
+//        List<PiMultiTaskRela> piMultiTaskRelaList = piMultiTaskRelaService.queryByMultiTaskId(multiTaskIds);
+//        Map<Long, List<PiMultiTaskRela>> piMultiTaskRelaMap =
+//                piMultiTaskRelaList.stream().collect(Collectors.groupingBy(PiMultiTaskRela::getMultiTaskId));
 
-        // 获取打卡任务信息,打卡任务唯一ID-打卡任务关联
+        // 获取打卡任务信息
         PiTaskQuery piTaskQuery = new PiTaskQuery();
         piTaskQuery.setTaskStatus(VersionStatusEnum.ACTIVE);
-        piTaskQuery.setArchiveStatus(ArchiveStatusEnum.ACTIVE);
         piTaskQuery.setUserIds(userIds);
         List<PiTask> piTasks = piTaskService.queryByCondition(piTaskQuery);
+
+        // 处理归档数据,以防归档任务早于结算任务执行
+        piTasks = piTasks.stream().filter(v -> {
+                    // 已归档(只有手动和自动两种可能)
+                    if (ArchiveStatusEnum.ARCHIVE.equals(v.getArchiveStatus())) {
+                        // 有手动归档日期,是主动归档 且 结算日期在手动归档日期前,则参与结算
+                        if (Objects.nonNull(v.getManualArchiveDate()) && punchInDate.isBefore(v.getManualArchiveDate())) {
+                            return true;
+                        }
+                        // 有自动归档日期,时自动归档 且 结算日期小于等于归档日期 参与结算
+                        if (Objects.nonNull(v.getAutoArchiveDate()) && punchInDate.compareTo(v.getAutoArchiveDate()) < 1) {
+                            return true;
+                        }
+                        // 其他情况应该不存在,不参与结算
+                        return false;
+                    }
+
+                    // 非已归档情况,参与结算
+                    return true;
+                }).toList();
+
+        // 打卡任务唯一ID-打卡任务关联
         Map<Long, List<PiTask>> piTaskMap =
                 piTasks.stream().collect(Collectors.groupingBy(PiTask::getCreatedBy));
 
         // 获取打卡记录,任务唯一 ID-打卡记录关联
         PiTaskHistoryQuery piTaskHistoryQuery = new PiTaskHistoryQuery();
-        piTaskHistoryQuery.setPunchInDate(punchInDateStr);
+        piTaskHistoryQuery.setPunchInDate(punchInDate.toString());
         piTaskHistoryQuery.setUserIds(userIds);
         List<PiTaskHistory> punchInTaskHistories = piTaskHistoryService.queryByCondition(piTaskHistoryQuery);
         Map<Long, PiTaskHistory> piTaskHistoryMap =

+ 28 - 0
src/main/java/com/punchsettle/server/task/SettlePointsTask.java

@@ -2,8 +2,12 @@ package com.punchsettle.server.task;
 
 import com.google.common.collect.Lists;
 import com.punchsettle.server.atomic.entity.SettleTaskHistory;
+import com.punchsettle.server.atomic.entity.SettleUserHistory;
 import com.punchsettle.server.atomic.service.ISettleTaskHistoryService;
+import com.punchsettle.server.atomic.service.ISettleUserHistoryService;
 import com.punchsettle.server.atomic.service.IUserService;
+import com.punchsettle.server.constant.SettleResultEnum;
+import com.punchsettle.server.pojo.settle.SettleUserHistoryQuery;
 import com.punchsettle.server.service.manager.ISettleManager;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -11,7 +15,10 @@ import org.springframework.stereotype.Component;
 import org.springframework.util.CollectionUtils;
 
 import java.time.LocalDate;
+import java.util.Arrays;
 import java.util.List;
+import java.util.Set;
+import java.util.stream.Collectors;
 
 /**
  * @author tyuio
@@ -32,6 +39,9 @@ public class SettlePointsTask {
     @Autowired
     private ISettleManager settleManager;
 
+    @Autowired
+    private ISettleUserHistoryService settleUserHistoryService;
+
     public void execute() {
         log.info("========== 打卡结算定时任务 开始执行 ==========");
 
@@ -56,6 +66,24 @@ public class SettlePointsTask {
      * @param punchInDate 结算的打卡打卡日期
      */
     public void settle(List<Long> userIds, String punchInDate) {
+        // 判断是否重复结算
+        SettleUserHistoryQuery settleUserHistoryQuery = new SettleUserHistoryQuery();
+        settleUserHistoryQuery.setSettleDate(punchInDate);
+        settleUserHistoryQuery.setUserIds(userIds);
+        settleUserHistoryQuery.setSettleResults(Arrays.asList(SettleResultEnum.SETTLE, SettleResultEnum.NO_SETTLED));
+        List<SettleUserHistory> settleUserHistories = settleUserHistoryService.querySettleUserHistory(settleUserHistoryQuery);
+        // 已结算的用户列表
+        Set<Long> settleUserIds = settleUserHistories.stream().map(SettleUserHistory::getUserId).collect(Collectors.toSet());
+
+        // 过滤已结算的用户
+        userIds = userIds.stream().filter(userId -> !settleUserIds.contains(userId)).toList();
+
+        // 没有需要结算的用户
+        if (CollectionUtils.isEmpty(userIds)) {
+            log.info("========== 打卡结算定时任务,没有需要结算的用户 结束执行 ==========");
+            return;
+        }
+
         // 数据入库
         SettleTaskHistory addSettleTaskHistory = new SettleTaskHistory();
         addSettleTaskHistory.setSettleDate(punchInDate);

+ 5 - 1
src/test/java/com/punchsettle/server/service/manager/impl/PunchInManagerImplTest.java

@@ -60,8 +60,12 @@ class PunchInManagerImplTest {
         Assertions.assertTrue(punchInManager.judgeRepeat(piTask5, LocalDate.parse("2025-04-26")));
 
         PiTask piTask6 = new PiTask();
-        piTask6.setEndDate(LocalDate.parse("2025-04-25"));
+        piTask6.setAutoArchiveDate(LocalDate.parse("2025-04-25"));
         Assertions.assertFalse(punchInManager.judgeRepeat(piTask6, LocalDate.parse("2025-04-26")));
+
+        PiTask piTask7 = new PiTask();
+        piTask7.setManualArchiveDate(LocalDate.parse("2025-04-25"));
+        Assertions.assertFalse(punchInManager.judgeRepeat(piTask7, LocalDate.parse("2025-04-26")));
     }
 
     @Test