浏览代码

【feat】【v3】
1.完善标注是
2.增加和修改打卡相关的逻辑

ChenYL 11 月之前
父节点
当前提交
50c85aeea3
共有 42 个文件被更改,包括 2041 次插入1216 次删除
  1. 2 2
      doc/sql/update-v3.sql
  2. 2 2
      doc/技术文档.md
  3. 54 0
      src/main/java/com/punchsettle/server/atomic/StatPiTask.java
  4. 4 3
      src/main/java/com/punchsettle/server/atomic/entity/PiMultiTask.java
  5. 4 3
      src/main/java/com/punchsettle/server/atomic/entity/PiTask.java
  6. 2 1
      src/main/java/com/punchsettle/server/atomic/entity/StatPiTaskMonth.java
  7. 2 1
      src/main/java/com/punchsettle/server/atomic/entity/StatPiTaskWeek.java
  8. 2 1
      src/main/java/com/punchsettle/server/atomic/entity/StatPiTaskYear.java
  9. 20 0
      src/main/java/com/punchsettle/server/atomic/service/IPiTaskHistoryService.java
  10. 19 0
      src/main/java/com/punchsettle/server/atomic/service/IPiTaskService.java
  11. 8 0
      src/main/java/com/punchsettle/server/atomic/service/IStatPiTaskMonthService.java
  12. 10 0
      src/main/java/com/punchsettle/server/atomic/service/IStatPiTaskYearService.java
  13. 35 0
      src/main/java/com/punchsettle/server/atomic/service/impl/PiTaskHistoryServiceImpl.java
  14. 24 2
      src/main/java/com/punchsettle/server/atomic/service/impl/PiTaskServiceImpl.java
  15. 11 0
      src/main/java/com/punchsettle/server/atomic/service/impl/StatPiTaskMonthServiceImpl.java
  16. 18 0
      src/main/java/com/punchsettle/server/atomic/service/impl/StatPiTaskYearServiceImpl.java
  17. 25 0
      src/main/java/com/punchsettle/server/constant/PunchInResultViewEnum.java
  18. 24 0
      src/main/java/com/punchsettle/server/constant/PunchInTaskStatusEnum.java
  19. 24 0
      src/main/java/com/punchsettle/server/constant/StatPeriodEnum.java
  20. 6 4
      src/main/java/com/punchsettle/server/pojo/punchIn/PiMultiTaskQuery.java
  21. 29 0
      src/main/java/com/punchsettle/server/pojo/punchIn/PiTaskExtRequest.java
  22. 20 0
      src/main/java/com/punchsettle/server/pojo/punchIn/PiTaskHistoryQuery.java
  23. 25 0
      src/main/java/com/punchsettle/server/pojo/punchIn/PiTaskHistorySimpleVO.java
  24. 50 0
      src/main/java/com/punchsettle/server/pojo/punchIn/PiTaskHistoryStatVO.java
  25. 3 2
      src/main/java/com/punchsettle/server/pojo/punchIn/PiTaskQuery.java
  26. 204 0
      src/main/java/com/punchsettle/server/pojo/punchIn/PiTaskRequest.java
  27. 79 0
      src/main/java/com/punchsettle/server/pojo/punchIn/PiTaskSimpleVO.java
  28. 30 0
      src/main/java/com/punchsettle/server/pojo/punchIn/PiTaskStatQuery.java
  29. 56 0
      src/main/java/com/punchsettle/server/pojo/punchIn/PiTaskStatVO.java
  30. 87 0
      src/main/java/com/punchsettle/server/pojo/punchIn/PiTaskToDoVO.java
  31. 173 0
      src/main/java/com/punchsettle/server/pojo/punchIn/PiTaskVO.java
  32. 27 0
      src/main/java/com/punchsettle/server/pojo/punchIn/PunchInRequest.java
  33. 55 41
      src/main/java/com/punchsettle/server/service/controller/PunchInController.java
  34. 66 0
      src/main/java/com/punchsettle/server/service/manager/IPunchInCoreManager.java
  35. 64 38
      src/main/java/com/punchsettle/server/service/manager/IPunchInManager.java
  36. 0 128
      src/main/java/com/punchsettle/server/service/manager/IPunchInManagerV1.java
  37. 226 0
      src/main/java/com/punchsettle/server/service/manager/impl/PunchInCoreManagerImpl.java
  38. 544 126
      src/main/java/com/punchsettle/server/service/manager/impl/PunchInManagerImpl.java
  39. 0 796
      src/main/java/com/punchsettle/server/service/manager/impl/PunchInManagerV1Impl.java
  40. 5 4
      src/main/java/com/punchsettle/server/service/manager/impl/PunchInSettleManagerImpl.java
  41. 0 60
      src/main/java/com/punchsettle/server/task/PunchInCoreTask.java
  42. 2 2
      src/test/java/com/punchsettle/server/service/manager/impl/PunchInManagerImplTest.java

+ 2 - 2
doc/sql/update-v3.sql

@@ -234,7 +234,7 @@ CREATE TABLE `pi_multi_task` (
   `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
   `user_id` bigint NOT NULL COMMENT '用户ID',
   `unique_id` bigint NOT NULL COMMENT '打卡多任务唯一ID',
-  `task_status` varchar(10) NOT NULL COMMENT '任务状态(活跃-ACTIVE,归档-ARCHIVE)',
+  `task_status` varchar(10) NOT NULL COMMENT '任务状态(活跃-ACTIVE,归档-ARCHIVE,删除-DELETE)',
   `task_version` int NOT NULL COMMENT '任务修改版本',
   `task_points_status` varchar(10) NOT NULL COMMENT '是否启用多任务积分计算(ENABLED-启用,DISABLED-关闭)',
   `punch_in_done_count` int DEFAULT NULL COMMENT '打卡完成次数',
@@ -524,7 +524,7 @@ ALTER TABLE punch_settle.pi_task MODIFY COLUMN points int DEFAULT 1 NOT NULL COM
 
 ALTER TABLE `pi_task`
 ADD COLUMN `unique_id` bigint NULL COMMENT '任务唯一ID',
-ADD COLUMN `task_status` varchar(10) NULL COMMENT '任务状态(活跃-ACTIVE,归档-ARCHIVE)',
+ADD COLUMN `task_status` varchar(10) NULL COMMENT '任务状态(活跃-ACTIVE,归档-ARCHIVE,删除-DELETE)',
 ADD COLUMN `task_version` int NULL COMMENT '任务修改版本',
 ADD COLUMN `end_date` date DEFAULT NULL  COMMENT '结束日期',
 ADD COLUMN `archive_status` varchar(10) NULL  COMMENT '是否归档(活跃-ACTIVE,归档-ARCHIVE)',

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

@@ -601,7 +601,7 @@ ui设计工具:即时设计
 | ----------------------------------- | ------------ | ------------------------------------------------------------ | -------- |
 | id                                  | bigint       | 主键                                                         | 主键索引 |
 | unique_id                           | bigint       | 任务唯一ID                                                   | 普通索引 |
-| task_status                         | varchar(10)  | 任务状态(活跃-ACTIVE,归档-ARCHIVE)                          |          |
+| task_status                         | varchar(10)  | 任务状态(活跃-ACTIVE,归档-ARCHIVE,删除-DELETE)             |          |
 | task_version                        | int          | 任务修改版本                                                 |          |
 | task_name                           | varchar(128) | 任务名称                                                     |          |
 | description                         | varchar(300) | 任务描述                                                     |          |
@@ -672,7 +672,7 @@ ui设计工具:即时设计
 | id                         | bigint      | 主键                                                | 主键索引 |
 | unique_id                  | bigint      | 打卡多任务唯一ID                                    | 普通索引 |
 | user_id                    | bigint      | 用户ID                                              | 普通索引 |
-| task_status                | varchar(10) | 任务状态(活跃-ACTIVE,归档-ARCHIVE)                 |          |
+| task_status                | varchar(10) | 任务状态(活跃-ACTIVE,归档-ARCHIVE,删除-DELETE)    |          |
 | task_version               | int         | 任务修改版本                                        |          |
 | task_points_status         | varchar(10) | 是否启用多任务积分计算(ENABLED-启用,DISABLED-关闭) |          |
 | punch_in_done_count        | int         | 打卡完成次数                                        |          |

+ 54 - 0
src/main/java/com/punchsettle/server/atomic/StatPiTask.java

@@ -0,0 +1,54 @@
+package com.punchsettle.server.atomic;
+
+import java.math.BigDecimal;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @date 2025/4/24 16:28
+ * @description 打卡任务数据统计
+ */
+public interface StatPiTask {
+
+    /**
+     * 获取任务唯一ID
+     * @return
+     */
+    Long getTaskUniqueId();
+
+    /**
+     * 获取统计时间
+     * @return
+     */
+    String getStatTime();
+
+    /**
+     * 本年需打卡数
+     */
+    Integer getPunchInTotalCount();
+
+    /**
+     * 本年已打卡数
+     */
+    Integer getPunchInCount();
+
+    /**
+     * 本年完成打卡数
+     */
+    Integer getPunchInDoneCount();
+
+    /**
+     * 本年打卡率
+     */
+    BigDecimal getPunchInRate();
+
+    /**
+     * 本年打卡完成率
+     */
+    BigDecimal getPunchInDoneRate();
+
+    /**
+     * 本年获取积分数
+     */
+    Integer getPoints();
+}

+ 4 - 3
src/main/java/com/punchsettle/server/atomic/entity/PiMultiTask.java

@@ -9,6 +9,7 @@ import com.punchsettle.server.common.pojo.BaseEntity;
 import com.punchsettle.server.constant.ArchiveStatusEnum;
 import com.punchsettle.server.common.constant.CommonEnableStatusEnum;
 import com.punchsettle.server.constant.PunchInExtraMethodEnum;
+import com.punchsettle.server.constant.PunchInTaskStatusEnum;
 import jakarta.persistence.Column;
 import jakarta.persistence.Table;
 import lombok.Data;
@@ -35,11 +36,11 @@ public class PiMultiTask extends BaseEntity implements Serializable, ContinueTas
     private Long uniqueId;
 
     /**
-     * 任务状态(活跃-ACTIVE,归档-ARCHIVE)
-     * @see ArchiveStatusEnum
+     * 任务状态(活跃-ACTIVE,归档-ARCHIVE,删除-DELETE)
+     * @see PunchInTaskStatusEnum
      */
     @Column(name = "task_status")
-    private ArchiveStatusEnum taskStatus;
+    private PunchInTaskStatusEnum taskStatus;
 
     /**
      * 任务修改版本

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

@@ -13,6 +13,7 @@ import com.punchsettle.server.constant.CompareRuleEnum;
 import com.punchsettle.server.constant.PunchInExtraMethodEnum;
 import com.punchsettle.server.constant.FullAttendancePeriodEnum;
 import com.punchsettle.server.constant.PunchInMethodEnum;
+import com.punchsettle.server.constant.PunchInTaskStatusEnum;
 import com.punchsettle.server.constant.RepeatCategoryEnum;
 import jakarta.persistence.Column;
 import jakarta.persistence.Table;
@@ -40,11 +41,11 @@ public class PiTask extends BaseEntity implements Serializable, ContinueTask {
     private Long uniqueId;
 
     /**
-     * 任务状态(活跃-ACTIVE,归档-ARCHIVE)
-     * @see ArchiveStatusEnum
+     * 任务状态(活跃-ACTIVE,归档-ARCHIVE,删除-DELETE)
+     * @see PunchInTaskStatusEnum
      */
     @Column(name = "task_status")
-    private ArchiveStatusEnum taskStatus;
+    private PunchInTaskStatusEnum taskStatus;
 
     /**
      * 任务修改版本

+ 2 - 1
src/main/java/com/punchsettle/server/atomic/entity/StatPiTaskMonth.java

@@ -4,6 +4,7 @@ import java.io.Serial;
 import java.io.Serializable;
 import java.math.BigDecimal;
 
+import com.punchsettle.server.atomic.StatPiTask;
 import com.punchsettle.server.common.pojo.BaseEntity;
 
 import jakarta.persistence.Column;
@@ -20,7 +21,7 @@ import lombok.EqualsAndHashCode;
 @Data
 @EqualsAndHashCode(callSuper = true)
 @Table(name = "stat_pi_task_month")
-public class StatPiTaskMonth extends BaseEntity implements Serializable {
+public class StatPiTaskMonth extends BaseEntity implements Serializable, StatPiTask {
 
     @Serial
     private static final long serialVersionUID = -590856736982272243L;

+ 2 - 1
src/main/java/com/punchsettle/server/atomic/entity/StatPiTaskWeek.java

@@ -4,6 +4,7 @@ import java.io.Serial;
 import java.io.Serializable;
 import java.math.BigDecimal;
 
+import com.punchsettle.server.atomic.StatPiTask;
 import com.punchsettle.server.common.pojo.BaseEntity;
 
 import jakarta.persistence.Column;
@@ -20,7 +21,7 @@ import lombok.EqualsAndHashCode;
 @Data
 @EqualsAndHashCode(callSuper = true)
 @Table(name = "stat_pi_task_week")
-public class StatPiTaskWeek extends BaseEntity implements Serializable {
+public class StatPiTaskWeek extends BaseEntity implements Serializable, StatPiTask {
 
     @Serial
     private static final long serialVersionUID = -590856736982272243L;

+ 2 - 1
src/main/java/com/punchsettle/server/atomic/entity/StatPiTaskYear.java

@@ -4,6 +4,7 @@ import java.io.Serial;
 import java.io.Serializable;
 import java.math.BigDecimal;
 
+import com.punchsettle.server.atomic.StatPiTask;
 import com.punchsettle.server.common.pojo.BaseEntity;
 
 import jakarta.persistence.Column;
@@ -20,7 +21,7 @@ import lombok.EqualsAndHashCode;
 @Data
 @EqualsAndHashCode(callSuper = true)
 @Table(name = "stat_pi_task_year")
-public class StatPiTaskYear extends BaseEntity implements Serializable {
+public class StatPiTaskYear extends BaseEntity implements Serializable, StatPiTask {
 
     @Serial
     private static final long serialVersionUID = 4320138404959615628L;

+ 20 - 0
src/main/java/com/punchsettle/server/atomic/service/IPiTaskHistoryService.java

@@ -20,9 +20,29 @@ public interface IPiTaskHistoryService {
      */
     List<PiTaskHistory> queryByCondition(PiTaskHistoryQuery piTaskHistoryQuery);
 
+    /**
+     * 根据任务唯一id和打卡日期查询打卡任务记录
+     * @param taskUniqueId 任务唯一id
+     * @param punchInDate 打卡日期
+     * @return
+     */
+    PiTaskHistory getByTaskUniqueIdAndPunchInDate(Long taskUniqueId, String punchInDate);
+
     /**
      * 批量更新打卡任务记录
      * @param punchInTaskHistories
      */
     void batchUpdate(List<PiTaskHistory> punchInTaskHistories);
+
+    /**
+     * 更新
+     * @param piTaskHistory
+     */
+    void update(PiTaskHistory piTaskHistory);
+
+    /**
+     * 新增
+     * @param piTaskHistory
+     */
+    void insert(PiTaskHistory piTaskHistory);
 }

+ 19 - 0
src/main/java/com/punchsettle/server/atomic/service/IPiTaskService.java

@@ -19,4 +19,23 @@ public interface IPiTaskService {
      * @return
      */
     List<PiTask> queryByCondition(PiTaskQuery piTaskQuery);
+
+    /**
+     * 根据主键查询打卡任务
+     * @param id
+     * @return
+     */
+    PiTask getById(Long id);
+
+    /**
+     * 新增
+     * @param piTask
+     */
+    void insert(PiTask piTask);
+
+    /**
+     * 更新
+     * @param piTask
+     */
+    void update(PiTask piTask);
 }

+ 8 - 0
src/main/java/com/punchsettle/server/atomic/service/IStatPiTaskMonthService.java

@@ -25,4 +25,12 @@ public interface IStatPiTaskMonthService {
      * @param statPiTaskMonthList
      */
     void insertList(List<StatPiTaskMonth> statPiTaskMonthList);
+
+    /**
+     * 查询用户统计数据
+     * @param userId 用户id
+     * @param statTime 统计时间
+     * @return
+     */
+    StatPiTaskMonth getByUserIdAndStatTime(Long userId, String statTime);
 }

+ 10 - 0
src/main/java/com/punchsettle/server/atomic/service/IStatPiTaskYearService.java

@@ -1,5 +1,7 @@
 package com.punchsettle.server.atomic.service;
 
+import com.punchsettle.server.atomic.entity.StatPiTaskYear;
+
 /**
  * @author tyuio
  * @version 1.0.0
@@ -7,4 +9,12 @@ package com.punchsettle.server.atomic.service;
  * @description 打卡任务年数据统计 service
  */
 public interface IStatPiTaskYearService {
+
+    /**
+     * 根据用户id和统计时间查询打卡任务年数据统计
+     * @param userId
+     * @param statTime
+     * @return
+     */
+    StatPiTaskYear getByUserIdAndStatTime(Long userId, String statTime);
 }

+ 35 - 0
src/main/java/com/punchsettle/server/atomic/service/impl/PiTaskHistoryServiceImpl.java

@@ -39,12 +39,47 @@ public class PiTaskHistoryServiceImpl implements IPiTaskHistoryService {
         if (StringUtils.hasText(piTaskHistoryQuery.getPunchInDate())) {
             criteria.andEqualTo(PiTaskHistory::getPunchInDate, piTaskHistoryQuery.getPunchInDate());
         }
+        if (!CollectionUtils.isEmpty(piTaskHistoryQuery.getTaskUniqueIds())) {
+            criteria.andIn(PiTaskHistory::getTaskUniqueId, piTaskHistoryQuery.getTaskUniqueIds());
+        }
+        if (StringUtils.hasText(piTaskHistoryQuery.getPunchInDateFrom())) {
+            criteria.andGreaterThanOrEqualTo(PiTaskHistory::getPunchInDate, piTaskHistoryQuery.getPunchInDateFrom());
+        }
+        if (StringUtils.hasText(piTaskHistoryQuery.getPunchInDateTo())) {
+            criteria.andLessThanOrEqualTo(PiTaskHistory::getPunchInDate, piTaskHistoryQuery.getPunchInDateTo());
+        }
+        if (StringUtils.hasText(piTaskHistoryQuery.getPunchInDateLike())) {
+            criteria.andLike(PiTaskHistory::getPunchInDate, String.format("%s%%", piTaskHistoryQuery.getPunchInDateLike()));
+        }
         return piTaskHistoryMapper.selectByExample(weekend);
     }
 
+    @Override
+    public PiTaskHistory getByTaskUniqueIdAndPunchInDate(Long taskUniqueId, String punchInDate) {
+        Assert.isNull(taskUniqueId);
+        Assert.isNull(punchInDate);
+
+        PiTaskHistory piTaskHistoryQuery = new PiTaskHistory();
+        piTaskHistoryQuery.setPunchInDate(punchInDate);
+        piTaskHistoryQuery.setTaskUniqueId(taskUniqueId);
+        return piTaskHistoryMapper.selectOne(piTaskHistoryQuery);
+    }
+
     @Override
     public void batchUpdate(List<PiTaskHistory> punchInTaskHistories) {
         Assert.notEmpty(punchInTaskHistories);
         piTaskHistoryMapper.batchUpdateSelective(punchInTaskHistories);
     }
+
+    @Override
+    public void update(PiTaskHistory piTaskHistory) {
+        Assert.isNull(piTaskHistory);
+        piTaskHistoryMapper.updateByPrimaryKeySelective(piTaskHistory);
+    }
+
+    @Override
+    public void insert(PiTaskHistory piTaskHistory) {
+        Assert.isNull(piTaskHistory);
+        piTaskHistoryMapper.insertSelective(piTaskHistory);
+    }
 }

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

@@ -44,11 +44,33 @@ public class PiTaskServiceImpl implements IPiTaskService {
             criteria.andEqualTo(PiTask::getArchiveStatus, piTaskQuery.getArchiveStatus());
         }
 
-        weekend.excludeProperties(BaseEntity::getCreationTime,
-                BaseEntity::getLastUpdatedBy,
+        weekend.excludeProperties(BaseEntity::getLastUpdatedBy,
                 BaseEntity::getLastUpdateTime,
                 BaseEntity::getVersion,
                 BaseEntity::getDeleteFlag);
         return piTaskMapper.selectByExample(weekend);
     }
+
+    @Override
+    public PiTask getById(Long id) {
+        if (Objects.isNull(id)) {
+            return null;
+        }
+
+        PiTask piTaskQuery = new PiTask();
+        piTaskQuery.setId(id);
+        return piTaskMapper.selectOne(piTaskQuery);
+    }
+
+    @Override
+    public void insert(PiTask piTask) {
+        Assert.isNull(piTask);
+        piTaskMapper.insertSelective(piTask);
+    }
+
+    @Override
+    public void update(PiTask piTask) {
+        Assert.isNull(piTask);
+        piTaskMapper.updateByPrimaryKeySelective(piTask);
+    }
 }

+ 11 - 0
src/main/java/com/punchsettle/server/atomic/service/impl/StatPiTaskMonthServiceImpl.java

@@ -47,4 +47,15 @@ public class StatPiTaskMonthServiceImpl implements IStatPiTaskMonthService {
         Assert.notEmpty(statPiTaskMonthList);
         statPiTaskMonthMapper.insertList(statPiTaskMonthList);
     }
+
+    @Override
+    public StatPiTaskMonth getByUserIdAndStatTime(Long userId, String statTime) {
+        Assert.isNull(userId);
+        Assert.isNull(statTime);
+
+        StatPiTaskMonth statPiTaskMonthQuery = new StatPiTaskMonth();
+        statPiTaskMonthQuery.setUserId(userId);
+        statPiTaskMonthQuery.setStatTime(statTime);
+        return statPiTaskMonthMapper.selectOne(statPiTaskMonthQuery);
+    }
 }

+ 18 - 0
src/main/java/com/punchsettle/server/atomic/service/impl/StatPiTaskYearServiceImpl.java

@@ -1,6 +1,10 @@
 package com.punchsettle.server.atomic.service.impl;
 
+import com.punchsettle.server.atomic.entity.StatPiTaskYear;
+import com.punchsettle.server.atomic.mapper.StatPiTaskYearMapper;
 import com.punchsettle.server.atomic.service.IStatPiTaskYearService;
+import com.punchsettle.server.common.utils.Assert;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 /**
@@ -11,4 +15,18 @@ import org.springframework.stereotype.Service;
  */
 @Service
 public class StatPiTaskYearServiceImpl implements IStatPiTaskYearService {
+
+    @Autowired
+    private StatPiTaskYearMapper statPiTaskYearMapper;
+
+    @Override
+    public StatPiTaskYear getByUserIdAndStatTime(Long userId, String statTime) {
+        Assert.isNull(userId);
+        Assert.isNull(statTime);
+
+        StatPiTaskYear statPiTaskYearQuery = new StatPiTaskYear();
+        statPiTaskYearQuery.setUserId(userId);
+        statPiTaskYearQuery.setStatTime(statTime);
+        return statPiTaskYearMapper.selectOne(statPiTaskYearQuery);
+    }
 }

+ 25 - 0
src/main/java/com/punchsettle/server/constant/PunchInResultViewEnum.java

@@ -0,0 +1,25 @@
+package com.punchsettle.server.constant;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @date 2025/4/24 9:56
+ * @description 页面打卡结果枚举(不需要打卡-NOT_NEED,UNDONE-未完成打卡任务,DONE-已完成打卡任务,FUTURE-未到打卡时间)
+ */
+@Getter
+@AllArgsConstructor
+public enum PunchInResultViewEnum {
+
+    NOT_NEED("不需要打卡"),
+    UNDONE("未完成打卡任务"),
+    DONE("已完成打卡任务"),
+    FUTURE("未到打卡时间");
+
+    /**
+     * 名称
+     */
+    private String name;
+}

+ 24 - 0
src/main/java/com/punchsettle/server/constant/PunchInTaskStatusEnum.java

@@ -0,0 +1,24 @@
+package com.punchsettle.server.constant;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @date 2025/4/24 12:11
+ * @description 任务状态枚举(活跃-ACTIVE,归档-ARCHIVE,删除-DELETE)
+ */
+@Getter
+@AllArgsConstructor
+public enum PunchInTaskStatusEnum {
+
+    ACTIVE("活跃"),
+    ARCHIVE("归档"),
+    DELETE("删除");
+
+    /**
+     * 名称
+     */
+    private String name;
+}

+ 24 - 0
src/main/java/com/punchsettle/server/constant/StatPeriodEnum.java

@@ -0,0 +1,24 @@
+package com.punchsettle.server.constant;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @date 2025/4/24 16:10
+ * @description 统计周期枚举(年-YEAR、月-MONTH、周-WEEK)
+ */
+@Getter
+@AllArgsConstructor
+public enum StatPeriodEnum {
+
+    YEAR("年"),
+    MONTH("月"),
+    WEEK("周");
+
+    /**
+     * 名称
+     */
+    private String name;
+}

+ 6 - 4
src/main/java/com/punchsettle/server/pojo/punchIn/PiMultiTaskQuery.java

@@ -1,10 +1,11 @@
 package com.punchsettle.server.pojo.punchIn;
 
-import com.punchsettle.server.constant.ArchiveStatusEnum;
-import lombok.Data;
-
 import java.util.Collection;
 
+import com.punchsettle.server.constant.PunchInTaskStatusEnum;
+
+import lombok.Data;
+
 /**
  * @author tyuio
  * @version 1.0.0
@@ -21,6 +22,7 @@ public class PiMultiTaskQuery {
 
     /**
      * 任务状态
+     * @see PunchInTaskStatusEnum
      */
-    private ArchiveStatusEnum multiTaskTaskStatus;
+    private PunchInTaskStatusEnum multiTaskTaskStatus;
 }

+ 29 - 0
src/main/java/com/punchsettle/server/pojo/punchIn/PiTaskExtRequest.java

@@ -0,0 +1,29 @@
+package com.punchsettle.server.pojo.punchIn;
+
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Positive;
+import lombok.Data;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @date 2025/4/24 15:30
+ * @description 打卡任务拓展信息
+ */
+@Data
+public class PiTaskExtRequest {
+
+    /**
+     * 起始值(单位:次)
+     */
+    @NotNull(message = "起始值不能为空")
+    @Positive(message = "起始值必须大于0")
+    private Integer initialValue;
+
+    /**
+     * 奖励的积分(额外)
+     */
+    @NotNull(message = "奖励的积分(额外)不能为空")
+    @Positive(message = "奖励的积分(额外)必须大于0")
+    private Integer extraPoints;
+}

+ 20 - 0
src/main/java/com/punchsettle/server/pojo/punchIn/PiTaskHistoryQuery.java

@@ -18,8 +18,28 @@ public class PiTaskHistoryQuery {
      */
     private Collection<Long> userIds;
 
+    /**
+     * 打卡任务唯一id列表
+     */
+    private Collection<Long> taskUniqueIds;
+
     /**
      * 打卡日期,格式:yyyy-MM-dd
      */
     private String punchInDate;
+
+    /**
+     * 打卡日期(开始),格式:yyyy-MM-dd
+     */
+    private String punchInDateFrom;
+
+    /**
+     * 打卡日期(结束),格式:yyyy-MM-dd
+     */
+    private String punchInDateTo;
+
+    /**
+     * 打卡日期(模糊查询)
+     */
+    private String punchInDateLike;
 }

+ 25 - 0
src/main/java/com/punchsettle/server/pojo/punchIn/PiTaskHistorySimpleVO.java

@@ -0,0 +1,25 @@
+package com.punchsettle.server.pojo.punchIn;
+
+import com.punchsettle.server.constant.PunchInResultViewEnum;
+import lombok.Data;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @date 2025/4/24 9:54
+ * @description 打卡记录简易 vo
+ */
+@Data
+public class PiTaskHistorySimpleVO {
+
+    /**
+     * 打卡日期
+     */
+    private String punchInDate;
+
+    /**
+     * 打卡结果
+     * @see PunchInResultViewEnum
+     */
+    private PunchInResultViewEnum punchInResult;
+}

+ 50 - 0
src/main/java/com/punchsettle/server/pojo/punchIn/PiTaskHistoryStatVO.java

@@ -0,0 +1,50 @@
+package com.punchsettle.server.pojo.punchIn;
+
+import java.time.LocalTime;
+
+import com.punchsettle.server.constant.PunchInResultEnum;
+import com.punchsettle.server.constant.SettleResultEnum;
+
+import lombok.Data;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @date 2025/4/24 16:04
+ * @description 打卡任务打卡记录统计 VO
+ */
+@Data
+public class PiTaskHistoryStatVO {
+
+    /**
+     * 打卡日期
+     */
+    private String punchInDate;
+
+    /**
+     * 次数记录
+     */
+    private Integer countTrack;
+
+    /**
+     * 时间记录
+     */
+    private LocalTime timeTrack;
+
+    /**
+     * 打卡结果(DONE-完成,UNDONE-未完成)
+     * @see PunchInResultEnum
+     */
+    private PunchInResultEnum punchInResult;
+
+    /**
+     * 结算结果(未结算-UNSETTLED,已结算-SETTLED)
+     * @see SettleResultEnum
+     */
+    private SettleResultEnum settleResult;
+
+    /**
+     * 结算奖励积分
+     */
+    private Integer settlePoints;
+}

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

@@ -3,6 +3,7 @@ package com.punchsettle.server.pojo.punchIn;
 import java.util.Collection;
 
 import com.punchsettle.server.constant.ArchiveStatusEnum;
+import com.punchsettle.server.constant.PunchInTaskStatusEnum;
 import lombok.Data;
 
 /**
@@ -21,9 +22,9 @@ public class PiTaskQuery {
 
     /**
      * 任务状态(活跃-ACTIVE,归档-ARCHIVE)
-     * @see ArchiveStatusEnum
+     * @see PunchInTaskStatusEnum
      */
-    private ArchiveStatusEnum taskStatus;
+    private PunchInTaskStatusEnum taskStatus;
 
     /**
      * 归档状态(活跃-ACTIVE,归档-ARCHIVE)

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

@@ -0,0 +1,204 @@
+package com.punchsettle.server.pojo.punchIn;
+
+import java.time.LocalDate;
+import java.time.LocalTime;
+import java.util.List;
+
+import org.hibernate.validator.constraints.Length;
+
+import com.punchsettle.server.common.constant.CommonEnableStatusEnum;
+import com.punchsettle.server.constant.CompareRuleEnum;
+import com.punchsettle.server.constant.FullAttendancePeriodEnum;
+import com.punchsettle.server.constant.PunchInExtraMethodEnum;
+import com.punchsettle.server.constant.PunchInMethodEnum;
+import com.punchsettle.server.constant.RepeatCategoryEnum;
+
+import jakarta.validation.Valid;
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import jakarta.validation.constraints.Positive;
+import lombok.Data;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @date 2025/4/24 15:02
+ * @description 打卡任务 请求
+ */
+@Data
+public class PiTaskRequest {
+
+    /**
+     * 任务ID
+     */
+    @NotNull(message = "打卡任务ID不能为空")
+    private Long id;
+
+    /**
+     * 任务名称
+     */
+    @NotBlank(message = "任务名称不能为空")
+    @Length(max = 30, message = "任务名称不能超过30个字符")
+    private String taskName;
+
+    /**
+     * 任务描述
+     */
+    private String description;
+
+    /**
+     * 奖励的积分(基本)
+     */
+    @NotNull(message = "奖励的积分不能为空")
+    @Positive(message = "奖励的积分必须大于0")
+    private Integer points;
+
+    /**
+     * 结束日期
+     */
+    private LocalDate endDate;
+
+    /**
+     * 显示顺序
+     */
+    private Integer displayOrder;
+
+    /**
+     * 显示时间
+     */
+    private LocalTime displayTime;
+
+    /**
+     * 打卡方式(单次打卡-SINGLE,计数-COUNT、计时-TIMING)
+     * @see PunchInMethodEnum
+     */
+    @NotNull(message = "打卡方式不能为空")
+    private PunchInMethodEnum punchInMethod;
+
+    /**
+     * 比较规则(大于等于-GTE,小于等于-LTE)
+     * @see CompareRuleEnum
+     */
+    private CompareRuleEnum compareRule;
+
+    /**
+     * 次数记录
+     */
+    private Integer countTrack;
+
+    /**
+     * 时间记录
+     */
+    private LocalTime timeTrack;
+
+    /**
+     * 是否启用节假日奖励(ENABLED-启用,DISABLED-关闭)
+     * @see CommonEnableStatusEnum
+     */
+    @NotNull(message = "是否启用节假日奖励不能为空")
+    private CommonEnableStatusEnum holidayStatus;
+
+    /**
+     * 次数记录(节假日用)
+     */
+    private Integer holidayCountTrack;
+
+    /**
+     * 时间记录(节假日用)
+     */
+    private LocalTime holidayTimeTrack;
+
+    /**
+     * 是否启用全勤奖励(ENABLED-启用,DISABLED-关闭)
+     * @see CommonEnableStatusEnum
+     */
+    @NotNull(message = "是否启用全勤奖励不能为空")
+    private CommonEnableStatusEnum fullAttendanceStatus;
+
+    /**
+     * 全勤周期(周-WEEK,月-MONTH)
+     * @see FullAttendancePeriodEnum
+     */
+    private FullAttendancePeriodEnum fullAttendancePeriod;
+
+    /**
+     * 全勤容错次数
+     */
+    private Integer fullAttendanceFaultToleranceCnt;
+
+    /**
+     * 重复周期类型(每日-EVERYDAY、法定工作日-WORKDAY、法定节假日(含周末)-HOLIDAY、自定义(周一至周日)-CUSTOM)
+     * @see RepeatCategoryEnum
+     */
+    @NotNull(message = "重复周期类型不能为空")
+    private RepeatCategoryEnum repeatCategory;
+
+    /**
+     * 自定义重复日(周一-1,周二-2,周三-3,周四-4,周五-5,周六-6,周日-7)
+     */
+    private String repeatCustomDay;
+
+    /**
+     * 额外奖励方式(无-NONE,固定-FIXED,区间-INTERVAL)
+     * @see PunchInExtraMethodEnum
+     */
+    @NotNull(message = "额外奖励方式不能为空")
+    private PunchInExtraMethodEnum extraMethod;
+
+    /**
+     * 额外的时间间隔(单位:分钟)
+     */
+    private Integer extraTimeStep;
+
+    /**
+     * 奖励的积分(额外)
+     */
+    private Integer extraPoints;
+
+    /**
+     * 是否启用连续规则(ENABLED-启用,DISABLED-关闭)
+     * @see CommonEnableStatusEnum
+     */
+    @NotNull(message = "是否启用连续规则不能为空")
+    private CommonEnableStatusEnum continueStatus;
+
+    /**
+     * 宽限期(单位:天)
+     */
+    private Integer graceDay;
+
+    /**
+     * 连续中断次数
+     */
+    private Integer continueInterruptedCount;
+
+    /**
+     * 惩罚天数(单位:天)
+     */
+    private Integer penaltyDay;
+
+    /**
+     * 是否启用自动打卡(ENABLED-启用,DISABLED-关闭)
+     * @see CommonEnableStatusEnum
+     */
+    @NotNull(message = "是否启用自动打卡不能为空")
+    private CommonEnableStatusEnum autoStatus;
+
+    /**
+     * 是否启用任务积分计算(ENABLED-启用,DISABLED-关闭)
+     * @see CommonEnableStatusEnum
+     */
+    @NotNull(message = "是否启用任务积分计算不能为空")
+    private CommonEnableStatusEnum taskPointsStatus;
+
+    /**
+     * 拓展信息(当天打卡)
+     */
+    private List<PiTaskExtRequest> taskExtList;
+
+    /**
+     * 拓展信息(连续打卡)
+     */
+    @Valid
+    private List<PiTaskExtRequest> continueTaskExtList;
+}

+ 79 - 0
src/main/java/com/punchsettle/server/pojo/punchIn/PiTaskSimpleVO.java

@@ -0,0 +1,79 @@
+package com.punchsettle.server.pojo.punchIn;
+
+import com.punchsettle.server.common.constant.CommonEnableStatusEnum;
+
+import com.punchsettle.server.constant.PunchInExtraMethodEnum;
+import lombok.Data;
+
+import java.util.List;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @date 2025/4/24 9:32
+ * @description 打卡任务简易 VO
+ */
+@Data
+public class PiTaskSimpleVO {
+
+    /**
+     * 主键
+     */
+    private Long id;
+
+    /**
+     * 任务名称
+     */
+    private String taskName;
+
+    /**
+     * 任务描述
+     */
+    private String description;
+
+    /**
+     * 奖励的积分(基本)
+     */
+    private Integer points;
+
+    /**
+     * 额外奖励方式(无-NONE,固定-FIXED,区间-INTERVAL)
+     * @see PunchInExtraMethodEnum
+     */
+    private PunchInExtraMethodEnum extraMethod;
+
+    /**
+     * 是否启用节假日奖励(ENABLED-启用,DISABLED-关闭)
+     * @see CommonEnableStatusEnum
+     */
+    private CommonEnableStatusEnum holidayStatus;
+
+    /**
+     * 是否启用全勤奖励(ENABLED-启用,DISABLED-关闭)
+     * @see CommonEnableStatusEnum
+     */
+    private CommonEnableStatusEnum fullAttendanceStatus;
+
+    /**
+     * 是否启用连续规则(ENABLED-启用,DISABLED-关闭)
+     * @see CommonEnableStatusEnum
+     */
+    private CommonEnableStatusEnum continueStatus;
+
+    /**
+     * 是否启用自动打卡(ENABLED-启用,DISABLED-关闭)
+     * @see CommonEnableStatusEnum
+     */
+    private CommonEnableStatusEnum autoStatus;
+
+    /**
+     * 是否启用任务积分计算(ENABLED-启用,DISABLED-关闭)
+     * @see CommonEnableStatusEnum
+     */
+    private CommonEnableStatusEnum taskPointsStatus;
+
+    /**
+     * 打卡记录
+     */
+    private List<PiTaskHistorySimpleVO> piTaskHistorySimpleVOS;
+}

+ 30 - 0
src/main/java/com/punchsettle/server/pojo/punchIn/PiTaskStatQuery.java

@@ -0,0 +1,30 @@
+package com.punchsettle.server.pojo.punchIn;
+
+import com.punchsettle.server.constant.StatPeriodEnum;
+
+import jakarta.validation.constraints.NotBlank;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @date 2025/4/24 16:09
+ * @description 打卡任务统计查询
+ */
+@Data
+public class PiTaskStatQuery {
+
+    /**
+     * 统计周期
+     * @see StatPeriodEnum
+     */
+    @NotNull(message = "统计周期不能为空")
+    private StatPeriodEnum statPeriod;
+
+    /**
+     * 统计周期时间
+     */
+    @NotBlank(message = "统计周期时间不能为空")
+    private String statTime;
+}

+ 56 - 0
src/main/java/com/punchsettle/server/pojo/punchIn/PiTaskStatVO.java

@@ -0,0 +1,56 @@
+package com.punchsettle.server.pojo.punchIn;
+
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @date 2025/4/24 16:01
+ * @description 打卡任务统计(年/月) VO
+ */
+@Data
+public class PiTaskStatVO {
+
+    /**
+     * 统计时间(格式:yyyy-MM)
+     */
+    private String statTime;
+
+    /**
+     * 本月需打卡数
+     */
+    private Integer punchInTotalCount;
+
+    /**
+     * 本月已打卡数
+     */
+    private Integer punchInCount;
+
+    /**
+     * 本月完成打卡数
+     */
+    private Integer punchInDoneCount;
+
+    /**
+     * 本月打卡率
+     */
+    private BigDecimal punchInRate;
+
+    /**
+     * 本月打卡完成率
+     */
+    private BigDecimal punchInDoneRate;
+
+    /**
+     * 本月获取积分数
+     */
+    private Integer points;
+
+    /**
+     * 打卡任务打卡记录统计
+     */
+    List<PiTaskHistoryStatVO> piTaskHistoryStatVOS;
+}

+ 87 - 0
src/main/java/com/punchsettle/server/pojo/punchIn/PiTaskToDoVO.java

@@ -0,0 +1,87 @@
+package com.punchsettle.server.pojo.punchIn;
+
+import java.time.LocalTime;
+
+import com.punchsettle.server.common.constant.CommonEnableStatusEnum;
+import com.punchsettle.server.constant.CompareRuleEnum;
+import com.punchsettle.server.constant.PunchInMethodEnum;
+
+import lombok.Data;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @date 2025/4/24 8:46
+ * @description 待办打卡任务 VO
+ */
+@Data
+public class PiTaskToDoVO {
+
+    /**
+     * 主键
+     */
+    private Long id;
+
+    /**
+     * 任务名称
+     */
+    private String taskName;
+
+    /**
+     * 任务描述
+     */
+    private String description;
+
+    /**
+     * 奖励的积分(基本)
+     */
+    private Integer points;
+
+    /**
+     * 打卡方式(单次打卡-SINGLE,计数-COUNT、计时-TIMING)
+     * @see PunchInMethodEnum
+     */
+    private PunchInMethodEnum punchInMethod;
+
+    /**
+     * 比较规则(大于等于-GTE,小于等于-LTE)
+     * @see CompareRuleEnum
+     */
+    private CompareRuleEnum compareRule;
+
+    /**
+     * 次数记录
+     */
+    private Integer countTrack;
+
+    /**
+     * 时间记录
+     */
+    private LocalTime timeTrack;
+
+    /**
+     * 是否启用节假日奖励(ENABLED-启用,DISABLED-关闭)
+     * @see CommonEnableStatusEnum
+     */
+    private CommonEnableStatusEnum holidayStatus;
+
+    /**
+     * 次数记录(节假日用)
+     */
+    private Integer holidayCountTrack;
+
+    /**
+     * 时间记录(节假日用)
+     */
+    private LocalTime holidayTimeTrack;
+
+    /**
+     * 次数记录(当前)
+     */
+    private Integer currentCountTrack;
+
+    /**
+     * 时间记录(当前)
+     */
+    private LocalTime currentTimeTrack;
+}

+ 173 - 0
src/main/java/com/punchsettle/server/pojo/punchIn/PiTaskVO.java

@@ -0,0 +1,173 @@
+package com.punchsettle.server.pojo.punchIn;
+
+import java.time.LocalDate;
+import java.time.LocalTime;
+
+import com.punchsettle.server.common.constant.CommonEnableStatusEnum;
+import com.punchsettle.server.constant.CompareRuleEnum;
+import com.punchsettle.server.constant.FullAttendancePeriodEnum;
+import com.punchsettle.server.constant.PunchInExtraMethodEnum;
+import com.punchsettle.server.constant.PunchInMethodEnum;
+import com.punchsettle.server.constant.RepeatCategoryEnum;
+
+import lombok.Data;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @date 2025/4/24 11:18
+ * @description 打卡任务 VO
+ */
+@Data
+public class PiTaskVO {
+
+    /**
+     * 任务ID
+     */
+    private Long id;
+
+    /**
+     * 任务名称
+     */
+    private String taskName;
+
+    /**
+     * 任务描述
+     */
+    private String description;
+
+    /**
+     * 奖励的积分(基本)
+     */
+    private Integer points;
+
+    /**
+     * 结束日期
+     */
+    private LocalDate endDate;
+
+    /**
+     * 显示顺序
+     */
+    private Integer displayOrder;
+
+    /**
+     * 显示时间
+     */
+    private LocalTime displayTime;
+
+    /**
+     * 打卡方式(单次打卡-SINGLE,计数-COUNT、计时-TIMING)
+     * @see PunchInMethodEnum
+     */
+    private PunchInMethodEnum punchInMethod;
+
+    /**
+     * 比较规则(大于等于-GTE,小于等于-LTE)
+     * @see CompareRuleEnum
+     */
+    private CompareRuleEnum compareRule;
+
+    /**
+     * 次数记录
+     */
+    private Integer countTrack;
+
+    /**
+     * 时间记录
+     */
+    private LocalTime timeTrack;
+
+    /**
+     * 是否启用节假日奖励(ENABLED-启用,DISABLED-关闭)
+     * @see CommonEnableStatusEnum
+     */
+    private CommonEnableStatusEnum holidayStatus;
+
+    /**
+     * 次数记录(节假日用)
+     */
+    private Integer holidayCountTrack;
+
+    /**
+     * 时间记录(节假日用)
+     */
+    private LocalTime holidayTimeTrack;
+
+    /**
+     * 是否启用全勤奖励(ENABLED-启用,DISABLED-关闭)
+     * @see CommonEnableStatusEnum
+     */
+    private CommonEnableStatusEnum fullAttendanceStatus;
+
+    /**
+     * 全勤周期(周-WEEK,月-MONTH)
+     * @see FullAttendancePeriodEnum
+     */
+    private FullAttendancePeriodEnum fullAttendancePeriod;
+
+    /**
+     * 全勤容错次数
+     */
+    private Integer fullAttendanceFaultToleranceCnt;
+
+    /**
+     * 重复周期类型(每日-EVERYDAY、法定工作日-WORKDAY、法定节假日(含周末)-HOLIDAY、自定义(周一至周日)-CUSTOM)
+     * @see RepeatCategoryEnum
+     */
+    private RepeatCategoryEnum repeatCategory;
+
+    /**
+     * 自定义重复日(周一-1,周二-2,周三-3,周四-4,周五-5,周六-6,周日-7)
+     */
+    private String repeatCustomDay;
+
+    /**
+     * 额外奖励方式(无-NONE,固定-FIXED,区间-INTERVAL)
+     * @see PunchInExtraMethodEnum
+     */
+    private PunchInExtraMethodEnum extraMethod;
+
+    /**
+     * 额外的时间间隔(单位:分钟)
+     */
+    private Integer extraTimeStep;
+
+    /**
+     * 奖励的积分(额外)
+     */
+    private Integer extraPoints;
+
+    /**
+     * 是否启用连续规则(ENABLED-启用,DISABLED-关闭)
+     * @see CommonEnableStatusEnum
+     */
+    private CommonEnableStatusEnum continueStatus;
+
+    /**
+     * 宽限期(单位:天)
+     */
+    private Integer graceDay;
+
+    /**
+     * 连续中断次数
+     */
+    private Integer continueInterruptedCount;
+
+    /**
+     * 惩罚天数(单位:天)
+     */
+    private Integer penaltyDay;
+
+    /**
+     * 是否启用自动打卡(ENABLED-启用,DISABLED-关闭)
+     * @see CommonEnableStatusEnum
+     */
+    private CommonEnableStatusEnum autoStatus;
+
+    /**
+     * 是否启用任务积分计算(ENABLED-启用,DISABLED-关闭)
+     * @see CommonEnableStatusEnum
+     */
+    private CommonEnableStatusEnum taskPointsStatus;
+}

+ 27 - 0
src/main/java/com/punchsettle/server/pojo/punchIn/PunchInRequest.java

@@ -0,0 +1,27 @@
+package com.punchsettle.server.pojo.punchIn;
+
+import java.time.LocalTime;
+
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @date 2025/4/24 14:33
+ * @description 打卡请求
+ */
+@Data
+public class PunchInRequest {
+
+    /**
+     * 打卡结算ID
+     */
+    @NotNull(message = "打卡任务ID不能为空")
+    private Long id;
+
+    /**
+     * 时间记录
+     */
+    private LocalTime timeTrack;
+}

+ 55 - 41
src/main/java/com/punchsettle/server/service/controller/PunchInController.java

@@ -2,25 +2,28 @@ package com.punchsettle.server.service.controller;
 
 import java.util.List;
 
+import com.punchsettle.server.pojo.punchIn.PiTaskRequest;
+import com.punchsettle.server.pojo.punchIn.PiTaskStatQuery;
+import com.punchsettle.server.pojo.punchIn.PiTaskStatVO;
+import com.punchsettle.server.pojo.punchIn.PunchInRequest;
+import com.punchsettle.server.pojo.punchIn.PiTaskSimpleVO;
+import com.punchsettle.server.pojo.punchIn.PiTaskToDoVO;
+import com.punchsettle.server.pojo.punchIn.PiTaskVO;
+import com.punchsettle.server.utiis.UserUtils;
+import jakarta.validation.constraints.NotNull;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.DeleteMapping;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 
-import com.punchsettle.server.common.valid.Delete;
-import com.punchsettle.server.common.valid.Query;
-import com.punchsettle.server.common.valid.Save;
-import com.punchsettle.server.common.valid.Update;
 import com.punchsettle.server.pojo.punchinV1.PunchInDataQuery;
 import com.punchsettle.server.pojo.punchinV1.PunchInDataVO;
 import com.punchsettle.server.pojo.punchinV1.PunchInRecordRequest;
-import com.punchsettle.server.pojo.punchinV1.PunchInRequest;
-import com.punchsettle.server.pojo.punchinV1.PunchInVO;
-import com.punchsettle.server.pojo.punchinV1.PunchInWithRecordVO;
-import com.punchsettle.server.service.manager.IPunchInManagerV1;
+import com.punchsettle.server.service.manager.IPunchInManager;
 
 /**
  * @author tyuio
@@ -28,74 +31,75 @@ import com.punchsettle.server.service.manager.IPunchInManagerV1;
  * @description 打卡任务 controller
  * @date 2024/11/25 14:48
  */
+@Validated
 @RestController
 @RequestMapping("/punchIn")
 public class PunchInController {
 
     @Autowired
-    private IPunchInManagerV1 punchInManager;
+    private IPunchInManager punchInManager;
 
     /**
-     * 查询打卡任务
+     * 查询待办列表
      */
-    @GetMapping("/queryPunchIns")
-    public List<PunchInWithRecordVO> queryPunchIns() {
-        return punchInManager.queryPunchInAndRecord();
+    @GetMapping("/queryToDoList")
+    public List<PiTaskToDoVO> queryToDoList() {
+        return punchInManager.queryToDoList(UserUtils.getCurrentUserId());
     }
 
     /**
-     * 查询指定打卡任务
-     * @param request
-     * @return
+     * 查询打卡任务(含打卡记录)列表
      */
-    @PostMapping("queryPunchInById")
-    public PunchInVO queryPunchInById(@RequestBody @Validated({Query.class}) PunchInRequest request) {
-        return punchInManager.queryPunchInById(request.getId());
+    @GetMapping("/queryTaskList")
+    public List<PiTaskSimpleVO> queryTaskList() {
+        return punchInManager.queryTaskList(UserUtils.getCurrentUserId());
     }
 
     /**
-     * 新增打卡任务
+     * 查询指定打卡任务
+     * @param id 任务id
+     * @return
      */
-    @PostMapping("/savePunchIn")
-    public void save(@RequestBody @Validated({Save.class}) PunchInRequest request) {
-        punchInManager.saveOrUpdatePunchIn(request);
+    @GetMapping("queryTask")
+    public PiTaskVO queryTask(@NotNull(message = "任务ID不能为空") Long id) {
+        return punchInManager.queryTask(id);
     }
 
     /**
-     * 更新打卡任务
+     * 保存打卡任务
      */
-    @PostMapping("/updatePunchIn")
-    public void update(@RequestBody @Validated({Update.class}) PunchInRequest request) {
-        punchInManager.saveOrUpdatePunchIn(request);
+    @PostMapping("/saveTask")
+    public void saveTask(@RequestBody PiTaskRequest request) {
+        punchInManager.saveTask(request);
     }
 
     /**
      * 删除打卡任务
      */
-    @PostMapping("/deletePunchIn")
-    public void delete(@RequestBody @Validated({Delete.class}) PunchInRequest request) {
-        punchInManager.deletePunchIn(request.getId());
+    @DeleteMapping("/deleteTask")
+    public void deleteTask(@NotNull(message = "任务ID不能为空") Long id) {
+        punchInManager.deleteTask(id);
     }
 
     /**
      * 打卡
      */
     @PostMapping("/doPunchIn")
-    public void doPunchIn(@RequestBody @Validated({PunchInRequest.DoPunchIn.class}) PunchInRequest request) {
+    public void doPunchIn(@RequestBody PunchInRequest request) {
         punchInManager.doPunchIn(request);
     }
 
     /**
-     * 归档
-     * @param request
+     * 打卡任务归档
+     * @param id 任务id
      */
-    @PostMapping("/archivePunchIn")
-    public void archivePunchIn(@RequestBody @Validated({PunchInRequest.Archive.class}) PunchInRequest request) {
-        punchInManager.archivePunchIn(request.getId());
+    @PostMapping("/archiveTask")
+    public void archiveTask(@NotNull(message = "任务ID不能为空") Long id) {
+        punchInManager.archiveTask(id);
     }
 
     /**
-     * 补打卡
+     * 补打卡 TODO 这里还没有修改
      */
     @PostMapping("/remakePunchIn")
     public void remakePunchIn(@RequestBody @Validated({PunchInRecordRequest.Remake.class}) PunchInRecordRequest request) {
@@ -103,12 +107,22 @@ public class PunchInController {
     }
 
     /**
-     * 撤销打卡
-     * @param request
+     * 撤销打卡
+     * @param id 打卡任务id
      */
     @PostMapping("/revokePunchIn")
-    public void revokePunchIn(@RequestBody @Validated({PunchInRecordRequest.Revoke.class}) PunchInRecordRequest request) {
-        punchInManager.revokePunchIn(request);
+    public void revokePunchIn(@NotNull(message = "任务ID不能为空") Long id) {
+        punchInManager.revokePunchIn(id);
+    }
+
+    /**
+     * 查询统计数据
+     * @param query
+     * @return
+     */
+    @GetMapping("/queryStat")
+    public PiTaskStatVO queryStat(@RequestBody PiTaskStatQuery query) {
+        return punchInManager.queryStat(query);
     }
 
     /**

+ 66 - 0
src/main/java/com/punchsettle/server/service/manager/IPunchInCoreManager.java

@@ -0,0 +1,66 @@
+package com.punchsettle.server.service.manager;
+
+import com.punchsettle.server.atomic.ContinueTask;
+import com.punchsettle.server.atomic.entity.PiMultiTask;
+import com.punchsettle.server.atomic.entity.PiStatus;
+import com.punchsettle.server.atomic.entity.PiTask;
+import com.punchsettle.server.atomic.entity.PiTaskHistory;
+import com.punchsettle.server.constant.ContinueStageEnum;
+import com.punchsettle.server.constant.PunchInResultEnum;
+import com.punchsettle.server.constant.RepeatCategoryEnum;
+
+import java.time.LocalDate;
+import java.util.List;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @date 2025/4/15 14:04
+ * @description 打卡核心服务类
+ */
+public interface IPunchInCoreManager {
+
+    /**
+     * 判断指定日期是否在打卡任务的重复周期内
+     * @param piTask 打卡任务
+     * @param repeatDateStr 指定日期
+     * @return true-在周期内,false-不在周期内
+     */
+    boolean judgeRepeat(PiTask piTask, String repeatDateStr);
+
+    /**
+     * 判断打卡结果
+     * @param piTask 当前打卡任务
+     * @param piTaskHistory 打卡记录
+     * @return
+     */
+    PunchInResultEnum judgePunchInResultInTask(PiTask piTask, PiTaskHistory piTaskHistory);
+
+    /**
+     * 判断打卡结果(多任务)
+     * @param piMultiTask 打卡多任务任务
+     * @param piTaskHistoryList 打卡记录
+     * @return
+     */
+    PunchInResultEnum judgePunchInResultInMultiTask(PiMultiTask piMultiTask, List<PiTaskHistory> piTaskHistoryList);
+
+    /**
+     * 根据重复类型计算指定日期范围内的总打卡次数
+     * @param repeatCategory 重复类型
+     * @param repeatCustomDay 自定义重复日(周一-1,周二-2,周三-3,周四-4,周五-5,周六-6,周日-7
+     * @param repeatStartDate 重复开始日期
+     * @param repeatEndDate 重复结束日期
+     * @return
+     */
+    int getPunchInTotalCountInRange(RepeatCategoryEnum repeatCategory, String repeatCustomDay, LocalDate repeatStartDate, LocalDate repeatEndDate);
+
+    /**
+     * 判断连续任务在指定日期的连续打卡阶段
+     * @param continueTask 连续任务
+     * @param punchInResult 打卡结果
+     * @param piStatus 打卡状态
+     * @param punchInDate 打卡日期
+     * @return
+     */
+    ContinueStageEnum judgeContinueStage(ContinueTask continueTask, PunchInResultEnum punchInResult, PiStatus piStatus, LocalDate punchInDate);
+}

+ 64 - 38
src/main/java/com/punchsettle/server/service/manager/IPunchInManager.java

@@ -1,66 +1,92 @@
 package com.punchsettle.server.service.manager;
 
-import com.punchsettle.server.atomic.ContinueTask;
-import com.punchsettle.server.atomic.entity.PiMultiTask;
-import com.punchsettle.server.atomic.entity.PiStatus;
-import com.punchsettle.server.atomic.entity.PiTask;
-import com.punchsettle.server.atomic.entity.PiTaskHistory;
-import com.punchsettle.server.constant.ContinueStageEnum;
-import com.punchsettle.server.constant.PunchInResultEnum;
-import com.punchsettle.server.constant.RepeatCategoryEnum;
-
-import java.time.LocalDate;
 import java.util.List;
 
+import com.punchsettle.server.pojo.punchIn.PiTaskRequest;
+import com.punchsettle.server.pojo.punchIn.PiTaskSimpleVO;
+import com.punchsettle.server.pojo.punchIn.PiTaskStatQuery;
+import com.punchsettle.server.pojo.punchIn.PiTaskStatVO;
+import com.punchsettle.server.pojo.punchIn.PiTaskToDoVO;
+import com.punchsettle.server.pojo.punchIn.PiTaskVO;
+import com.punchsettle.server.pojo.punchIn.PunchInRequest;
+import com.punchsettle.server.pojo.punchinV1.PunchInDataQuery;
+import com.punchsettle.server.pojo.punchinV1.PunchInDataVO;
+import com.punchsettle.server.pojo.punchinV1.PunchInRecordRequest;
+
 /**
  * @author tyuio
  * @version 1.0.0
- * @date 2025/4/15 14:04
- * @description 打卡服务类
+ * @description 打卡结算任务 服务类
+ * @date 2024/11/25 15:00
  */
 public interface IPunchInManager {
 
     /**
-     * 判断指定日期是否在打卡任务的重复周期内
-     * @param piTask 打卡任务
-     * @param repeatDateStr 指定日期
-     * @return true-在周期内,false-不在周期内
+     * 查询待办打卡任务列表
+     * @param currentUserId 当前用户id
+     * @return
      */
-    boolean judgeRepeat(PiTask piTask, String repeatDateStr);
+    List<PiTaskToDoVO> queryToDoList(Long currentUserId);
 
     /**
-     * 判断打卡结果
-     * @param piTask 当前打卡任务
-     * @param piTaskHistory 打卡记录
+     * 查询打卡任务及其打卡记录
+     * @param currentUserId 当前用户id
      * @return
      */
-    PunchInResultEnum judgePunchInResultInTask(PiTask piTask, PiTaskHistory piTaskHistory);
+    List<PiTaskSimpleVO> queryTaskList(Long currentUserId);
 
     /**
-     * 判断打卡结果(多任务)
-     * @param piMultiTask 打卡多任务任务
-     * @param piTaskHistoryList 打卡记录
-     * @return
+     * 根据ID获取打卡任务
+     */
+    PiTaskVO queryTask(Long id);
+
+    /**
+     * 保存打卡任务
+     * @param request 打卡任务
+     */
+    void saveTask(PiTaskRequest request);
+
+    /**
+     * 根据主键删除打卡任务
+     * @param id 主键
+     */
+    void deleteTask(Long id);
+
+    /**
+     * 打卡
+     * @param request
+     */
+    void doPunchIn(PunchInRequest request);
+
+    /**
+     * 归档打卡任务
+     * @param punchInId
+     */
+    void archiveTask(Long punchInId);
+
+    /**
+     * 补打卡
+     * @param request
+     */
+    void remakePunchIn(PunchInRecordRequest request);
+
+    /**
+     * 撤销误打卡
+     * @param id 打卡任务
      */
-    PunchInResultEnum judgePunchInResultInMultiTask(PiMultiTask piMultiTask, List<PiTaskHistory> piTaskHistoryList);
+    void revokePunchIn(Long id);
 
     /**
-     * 根据重复类型计算指定日期范围内的总打卡次数
-     * @param repeatCategory 重复类型
-     * @param repeatCustomDay 自定义重复日(周一-1,周二-2,周三-3,周四-4,周五-5,周六-6,周日-7
-     * @param repeatStartDate 重复开始日期
-     * @param repeatEndDate 重复结束日期
+     * 查询统计数据
+     * @param query
      * @return
      */
-    int getPunchInTotalCountInRange(RepeatCategoryEnum repeatCategory, String repeatCustomDay, LocalDate repeatStartDate, LocalDate repeatEndDate);
+    PiTaskStatVO queryStat(PiTaskStatQuery query);
 
     /**
-     * 判断连续任务在指定日期的连续打卡阶段
-     * @param continueTask 连续任务
-     * @param punchInResult 打卡结果
-     * @param piStatus 打卡状态
-     * @param punchInDate 打卡日期
+     * 查询打卡数据
+     * @param query
      * @return
      */
-    ContinueStageEnum judgeContinueStage(ContinueTask continueTask, PunchInResultEnum punchInResult, PiStatus piStatus, LocalDate punchInDate);
+    PunchInDataVO queryPunchInData(PunchInDataQuery query);
 }

+ 0 - 128
src/main/java/com/punchsettle/server/service/manager/IPunchInManagerV1.java

@@ -1,128 +0,0 @@
-package com.punchsettle.server.service.manager;
-
-import java.util.List;
-
-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.StatPiTaskMonth;
-import com.punchsettle.server.atomic.entity.StatPiTaskWeek;
-import com.punchsettle.server.atomic.entity.PiStatus;
-import com.punchsettle.server.atomic.entity.PiTask;
-import com.punchsettle.server.atomic.entity.PiTaskExt;
-import com.punchsettle.server.atomic.entity.PiTaskHistory;
-import com.punchsettle.server.constant.PunchInResultEnum;
-import com.punchsettle.server.pojo.punchinV1.PunchInDataQuery;
-import com.punchsettle.server.pojo.punchinV1.PunchInDataVO;
-import com.punchsettle.server.pojo.punchinV1.PunchInRecordRequest;
-import com.punchsettle.server.pojo.punchinV1.PunchInRequest;
-import com.punchsettle.server.pojo.punchinV1.PunchInVO;
-import com.punchsettle.server.pojo.punchinV1.PunchInWithRecordVO;
-
-/**
- * @author tyuio
- * @version 1.0.0
- * @description 打卡结算任务 服务类
- * @date 2024/11/25 15:00
- */
-public interface IPunchInManagerV1 {
-
-    /**
-     * 查询打卡任务及其打卡记录
-     * @return
-     */
-    List<PunchInWithRecordVO> queryPunchInAndRecord();
-
-    /**
-     * 根据ID获取打卡任务
-     */
-    PunchInVO queryPunchInById(Long punchInId);
-
-    /**
-     * 新增或更新打卡结算任务
-     * @param request 打卡结算
-     */
-    void saveOrUpdatePunchIn(PunchInRequest request);
-
-    /**
-     * 根据主键删除打卡结算任务
-     * @param punchInId 主键
-     */
-    void deletePunchIn(Long punchInId);
-
-    /**
-     * 完成打卡结算任务插入打卡记录
-     * @param request
-     */
-    void doPunchIn(PunchInRequest request);
-
-    /**
-     * 归档打卡任务
-     * @param punchInId
-     */
-    void archivePunchIn(Long punchInId);
-
-    /**
-     * 补打卡
-     * @param request
-     */
-    void remakePunchIn(PunchInRecordRequest request);
-
-    /**
-     * 撤销误打卡
-     * @param request
-     */
-    void revokePunchIn(PunchInRecordRequest request);
-
-    /**
-     * 查询打卡数据
-     * @param query
-     * @return
-     */
-    PunchInDataVO queryPunchInData(PunchInDataQuery query);
-
-    /**
-     * 判断指定日期是否在打卡任务的重复周期内
-     * @param piTask 打卡任务
-     * @param repeatDateStr 指定日期
-     * @return true-在周期内,false-不在周期内
-     */
-    boolean judgeRepeat(PiTask piTask, String repeatDateStr);
-
-    /**
-     * 判断打卡状态
-     * @param piTask 当前打卡任务
-     * @param piTaskHistory 打卡记录
-     * @param holidayFlag 是否是节假日(是-true,否-false)
-     * @return
-     */
-    PunchInResultEnum judgePunchInStatusInTask(PiTask piTask, PiTaskHistory piTaskHistory, boolean holidayFlag);
-
-    /**
-     * 判断打卡状态(多任务)
-     * @param piMultiTask 打卡多任务任务
-     * @param piTaskHistoryList 打卡记录
-     * @param multiTaskNum 参与多任务计算数量
-     * @return
-     */
-    PunchInResultEnum judgePunchInStatusInMultiTask(PiMultiTask piMultiTask, List<PiTaskHistory> piTaskHistoryList, int multiTaskNum);
-
-    /**
-     * 计算任务积分
-     * @param piTask 打卡任务
-     * @param piTaskExtList 打卡任务拓展信息列表
-     * @param piTaskHistory 打卡记录
-     * @return
-     */
-    int calculatePointsInTask(PiTask piTask, List<PiTaskExt> piTaskExtList, PiTaskHistory piTaskHistory, StatPiTaskWeek statPiTaskWeek, StatPiTaskMonth statPiTaskMonth, PiStatus piStatus);
-
-
-    /**
-     * 计算多任务积分
-     * @param piMultiTask
-     * @param piMultiTaskExts
-     * @param piMultiTaskHistory
-     * @return
-     */
-    int calculatePointsInMultiTask(PiMultiTask piMultiTask, List<PiMultiTaskExt> piMultiTaskExts, PiMultiTaskHistory piMultiTaskHistory, PiStatus piStatus);
-}

+ 226 - 0
src/main/java/com/punchsettle/server/service/manager/impl/PunchInCoreManagerImpl.java

@@ -0,0 +1,226 @@
+package com.punchsettle.server.service.manager.impl;
+
+import java.time.LocalDate;
+import java.time.LocalTime;
+import java.time.temporal.ChronoUnit;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+import com.punchsettle.server.atomic.ContinueTask;
+import com.punchsettle.server.atomic.entity.PiStatus;
+import com.punchsettle.server.constant.ContinueStageEnum;
+import com.punchsettle.server.utiis.DateUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.StringUtils;
+
+import com.punchsettle.server.atomic.entity.PiMultiTask;
+import com.punchsettle.server.atomic.entity.PiTask;
+import com.punchsettle.server.atomic.entity.PiTaskHistory;
+import com.punchsettle.server.common.constant.CommonEnableStatusEnum;
+import com.punchsettle.server.common.exception.BusinessException;
+import com.punchsettle.server.common.utils.Assert;
+import com.punchsettle.server.constant.CompareRuleEnum;
+import com.punchsettle.server.constant.PunchInMethodEnum;
+import com.punchsettle.server.constant.PunchInResultEnum;
+import com.punchsettle.server.constant.RepeatCategoryEnum;
+import com.punchsettle.server.service.manager.ICalendarManager;
+import com.punchsettle.server.service.manager.IPunchInCoreManager;
+
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @date 2025/4/15 14:10
+ * @description 打卡核心 服务类
+ */
+@Slf4j
+@Component
+public class PunchInCoreManagerImpl implements IPunchInCoreManager {
+
+    @Autowired
+    private ICalendarManager calendarManager;
+
+    @Override
+    public boolean judgeRepeat(PiTask piTask, String repeatDateStr) {
+        // 每天
+        if (RepeatCategoryEnum.EVERYDAY.equals(piTask.getRepeatCategory())) {
+            return true;
+        }
+
+        // 法定工作日
+        if (RepeatCategoryEnum.WORKDAY.equals(piTask.getRepeatCategory())) {
+            return calendarManager.judgeWorkday(repeatDateStr);
+        }
+
+        // 法定节假日(含周末)
+        if (RepeatCategoryEnum.HOLIDAY.equals(piTask.getRepeatCategory())) {
+            return calendarManager.judgeHoliday(repeatDateStr);
+        }
+
+        // 自定义
+        if (RepeatCategoryEnum.CUSTOM.equals(piTask.getRepeatCategory())) {
+            if (!StringUtils.hasText(piTask.getRepeatCustomDay())) {
+                BusinessException.throwFail(String.format("打卡任务ID:%s, 重复周期类型:自定义重复,没有设定自定义重复日期"));
+            }
+
+            LocalDate repeatDate = LocalDate.parse(repeatDateStr);
+            int dayOfWeekValue = repeatDate.getDayOfWeek().getValue();
+            return piTask.getRepeatCustomDay().contains(String.valueOf(dayOfWeekValue));
+        }
+
+        return false;
+    }
+
+    @Override
+    public PunchInResultEnum judgePunchInResultInTask(PiTask piTask, PiTaskHistory piTaskHistory) {
+        Assert.isNullInBusiness(piTask, "打卡任务不能为空 ");
+
+        // 没有打卡记录,直接没完成
+        if (Objects.isNull(piTaskHistory)) {
+            return PunchInResultEnum.UNDONE;
+        }
+
+        // 单次打卡,不区分是否节假日
+        if (PunchInMethodEnum.SINGLE.equals(piTask.getPunchInMethod())) {
+            int countTrack = Optional.ofNullable(piTaskHistory.getCountTrack()).orElse(0);
+            return countTrack > 0 ? PunchInResultEnum.DONE : PunchInResultEnum.UNDONE;
+        }
+
+        // 打卡任务的节假日启用配置
+        CommonEnableStatusEnum holidayStatus = Optional.ofNullable(piTask.getHolidayStatus()).orElse(CommonEnableStatusEnum.DISABLED);
+        boolean enableHolidayFlag = CommonEnableStatusEnum.ENABLED.equals(holidayStatus) && calendarManager.judgeHoliday(piTaskHistory.getPunchInDate());
+
+        // 计数打卡,要区分是否节假日使用不同的判断标准
+        if (PunchInMethodEnum.COUNT.equals(piTask.getPunchInMethod())) {
+            int countTrack = enableHolidayFlag ? piTask.getHolidayCountTrack() : piTask.getCountTrack();
+            int punchInCountTrack = Optional.ofNullable(piTaskHistory.getCountTrack()).orElse(0);
+            if (CompareRuleEnum.GTE.equals(piTask.getCompareRule()) && punchInCountTrack >= countTrack) {
+                return PunchInResultEnum.DONE;
+            }
+            if (CompareRuleEnum.LTE.equals(piTask.getCompareRule()) && punchInCountTrack <= countTrack) {
+                return PunchInResultEnum.DONE;
+            }
+            return PunchInResultEnum.UNDONE;
+        }
+
+        // 计时打卡,要区分是否节假日使用不同的判断标准
+        if (PunchInMethodEnum.TIMING.equals(piTask.getPunchInMethod())) {
+            LocalTime timeTrack = enableHolidayFlag ? piTask.getHolidayTimeTrack() : piTask.getTimeTrack();
+            LocalTime punchInTimeTrack = Optional.ofNullable(piTaskHistory.getTimeTrack()).orElse(LocalTime.parse("00:00:00.000"));
+            if (CompareRuleEnum.GTE.equals(piTask.getCompareRule()) && punchInTimeTrack.compareTo(timeTrack) > -1) {
+                return PunchInResultEnum.DONE;
+            }
+            if (CompareRuleEnum.LTE.equals(piTask.getCompareRule()) && punchInTimeTrack.compareTo(timeTrack) < 1) {
+                return PunchInResultEnum.DONE;
+            }
+
+            return PunchInResultEnum.UNDONE;
+        }
+
+        return PunchInResultEnum.UNDONE;
+    }
+
+    @Override
+    public PunchInResultEnum judgePunchInResultInMultiTask(PiMultiTask piMultiTask, List<PiTaskHistory> piTaskHistoryList) {
+        // 没有打卡记录 或者 没有启用多任务 则直接返回未完成
+        if (CollectionUtils.isEmpty(piTaskHistoryList) || CommonEnableStatusEnum.DISABLED.equals(piMultiTask.getTaskPointsStatus())) {
+            return PunchInResultEnum.UNDONE;
+        }
+
+        // 完成的打卡数量
+        long punchInDoneCount = piTaskHistoryList.stream().filter(v -> PunchInResultEnum.DONE.equals(v.getPunchInResult())).count();
+
+        // 当天打卡次数大于等于设置的次数,则完成打卡
+        // 没有设置时默认设置一个较大的数,避免出现打卡次数为0的情况
+        Integer doneCount = Optional.ofNullable(piMultiTask.getPunchInDoneCount()).orElse(piTaskHistoryList.size() + 1);
+        return punchInDoneCount >= doneCount ? PunchInResultEnum.DONE : PunchInResultEnum.UNDONE;
+    }
+
+    @Override
+    public int getPunchInTotalCountInRange(RepeatCategoryEnum repeatCategory, String repeatCustomDay, LocalDate repeatStartDate, LocalDate repeatEndDate) {
+
+        if (RepeatCategoryEnum.EVERYDAY.equals(repeatCategory)) {
+            return (int) ChronoUnit.DAYS.between(repeatStartDate, repeatEndDate.plusDays(1));
+        }
+
+        List<LocalDate> dateRange = DateUtils.getDateRange(repeatStartDate, repeatEndDate);
+
+        if (RepeatCategoryEnum.CUSTOM.equals(repeatCategory)) {
+            String[] split = repeatCustomDay.split(",");
+            Set<Integer> customDays = Arrays.stream(split).map(v -> Integer.valueOf(v)).collect(Collectors.toSet());
+            return (int) dateRange.stream().map(v -> v.getDayOfWeek().getValue()).filter(customDays::contains).count();
+        }
+
+        if (RepeatCategoryEnum.WORKDAY.equals(repeatCategory)) {
+            return (int) dateRange.stream().map(v -> DateUtils.YYYY_MM_DD_FORMATTER.format(v))
+                    .filter(v -> calendarManager.judgeWorkday(v)).count();
+        }
+
+        if (RepeatCategoryEnum.HOLIDAY.equals(repeatCategory)) {
+            return (int) dateRange.stream().map(v -> DateUtils.YYYY_MM_DD_FORMATTER.format(v))
+                    .filter(v -> calendarManager.judgeHoliday(v)).count();
+        }
+
+        return 0;
+    }
+
+    @Override
+    public ContinueStageEnum judgeContinueStage(ContinueTask continueTask, PunchInResultEnum punchInResult, PiStatus piStatus, LocalDate punchInDate) {
+        if (CommonEnableStatusEnum.DISABLED.equals(continueTask.getContinueStatus())) {
+            return ContinueStageEnum.NONE;
+        }
+
+        // TODO 启用/关闭连续打卡规则时要对状态表进行数据初始化
+
+        // 宽限期
+        if (ContinueStageEnum.GRACE_STAGE.equals(piStatus.getContinueStage())) {
+            LocalDate graceDay = piStatus.getStageStartDate().plusDays(continueTask.getGraceDay());
+            // 仍处于宽限期限内
+            if (punchInDate.compareTo(graceDay) <= 0) {
+                return ContinueStageEnum.GRACE_STAGE;
+            }
+
+            // 已超过宽限期限,但是未完成打卡
+            if (PunchInResultEnum.UNDONE.equals(punchInResult)) {
+                return ContinueStageEnum.GRACE_STAGE;
+            }
+
+            // 已超过宽限期限,且已完成打卡,进入正常打卡期
+            return ContinueStageEnum.NORMAL_STAGE;
+        }
+
+        // 正常打卡期
+        if (ContinueStageEnum.NORMAL_STAGE.equals(piStatus.getContinueStage())) {
+            // 完成打卡则继续是正常打卡期,否则是惩罚期
+            if (PunchInResultEnum.DONE.equals(punchInResult)) {
+                return ContinueStageEnum.NORMAL_STAGE;
+            }
+
+            // 连续中断次数大于等于设置的中断次数,重新进入宽限期,这里加1是因为需要加上本次的中断次数
+            if (piStatus.getContinueInterruptedCount() + 1 > continueTask.getContinueInterruptedCount()) {
+                return ContinueStageEnum.GRACE_STAGE;
+            }
+
+            return ContinueStageEnum.PENALTY_STAGE;
+        }
+
+        // 惩罚期
+        if (ContinueStageEnum.PENALTY_STAGE.equals(piStatus.getContinueStage())) {
+            // 仍处于惩罚期
+            if (punchInDate.compareTo(piStatus.getStageEndDate()) <= 0) {
+                return ContinueStageEnum.PENALTY_STAGE;
+            }
+
+            return ContinueStageEnum.NORMAL_STAGE;
+        }
+
+        return ContinueStageEnum.NONE;
+    }
+}

+ 544 - 126
src/main/java/com/punchsettle/server/service/manager/impl/PunchInManagerImpl.java

@@ -1,226 +1,644 @@
 package com.punchsettle.server.service.manager.impl;
 
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.text.SimpleDateFormat;
 import java.time.LocalDate;
 import java.time.LocalTime;
+import java.time.YearMonth;
 import java.time.temporal.ChronoUnit;
+import java.util.ArrayList;
 import java.util.Arrays;
+import java.util.Comparator;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
+import java.util.function.Function;
 import java.util.stream.Collectors;
 
-import com.punchsettle.server.atomic.ContinueTask;
-import com.punchsettle.server.atomic.entity.PiStatus;
-import com.punchsettle.server.constant.ContinueStageEnum;
-import com.punchsettle.server.utiis.DateUtils;
+import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.CollectionUtils;
 import org.springframework.util.StringUtils;
 
-import com.punchsettle.server.atomic.entity.PiMultiTask;
+import com.punchsettle.server.atomic.StatPiTask;
 import com.punchsettle.server.atomic.entity.PiTask;
 import com.punchsettle.server.atomic.entity.PiTaskHistory;
+import com.punchsettle.server.atomic.entity.PunchIn;
+import com.punchsettle.server.atomic.entity.PunchInRecord;
+import com.punchsettle.server.atomic.service.IPiTaskHistoryService;
+import com.punchsettle.server.atomic.service.IPiTaskService;
+import com.punchsettle.server.atomic.service.IPunchInRecordService;
+import com.punchsettle.server.atomic.service.IPunchInService;
+import com.punchsettle.server.atomic.service.IStatPiTaskMonthService;
+import com.punchsettle.server.atomic.service.IStatPiTaskYearService;
 import com.punchsettle.server.common.constant.CommonEnableStatusEnum;
 import com.punchsettle.server.common.exception.BusinessException;
 import com.punchsettle.server.common.utils.Assert;
-import com.punchsettle.server.constant.CompareRuleEnum;
+import com.punchsettle.server.constant.ArchiveStatusEnum;
+import com.punchsettle.server.constant.PunchInExtraMethodEnum;
 import com.punchsettle.server.constant.PunchInMethodEnum;
 import com.punchsettle.server.constant.PunchInResultEnum;
+import com.punchsettle.server.constant.PunchInResultViewEnum;
+import com.punchsettle.server.constant.PunchInSettleTypeEnum;
+import com.punchsettle.server.constant.PunchInStatusV1Enum;
+import com.punchsettle.server.constant.PunchInTaskStatusEnum;
 import com.punchsettle.server.constant.RepeatCategoryEnum;
-import com.punchsettle.server.service.manager.ICalendarManager;
+import com.punchsettle.server.constant.StatPeriodEnum;
+import com.punchsettle.server.pojo.punchIn.PiTaskHistoryQuery;
+import com.punchsettle.server.pojo.punchIn.PiTaskHistorySimpleVO;
+import com.punchsettle.server.pojo.punchIn.PiTaskHistoryStatVO;
+import com.punchsettle.server.pojo.punchIn.PiTaskQuery;
+import com.punchsettle.server.pojo.punchIn.PiTaskRequest;
+import com.punchsettle.server.pojo.punchIn.PiTaskSimpleVO;
+import com.punchsettle.server.pojo.punchIn.PiTaskStatQuery;
+import com.punchsettle.server.pojo.punchIn.PiTaskStatVO;
+import com.punchsettle.server.pojo.punchIn.PiTaskToDoVO;
+import com.punchsettle.server.pojo.punchIn.PiTaskVO;
+import com.punchsettle.server.pojo.punchIn.PunchInRequest;
+import com.punchsettle.server.pojo.punchinV1.PunchInCalendarDataVO;
+import com.punchsettle.server.pojo.punchinV1.PunchInDataQuery;
+import com.punchsettle.server.pojo.punchinV1.PunchInDataVO;
+import com.punchsettle.server.pojo.punchinV1.PunchInRecordDataVO;
+import com.punchsettle.server.pojo.punchinV1.PunchInRecordQuery;
+import com.punchsettle.server.pojo.punchinV1.PunchInRecordRequest;
+import com.punchsettle.server.service.manager.IPunchInCoreManager;
 import com.punchsettle.server.service.manager.IPunchInManager;
+import com.punchsettle.server.service.manager.ISettleManagerV1;
+import com.punchsettle.server.utiis.DateUtils;
+import com.punchsettle.server.utiis.UserUtils;
 
 import lombok.extern.slf4j.Slf4j;
 
 /**
  * @author tyuio
  * @version 1.0.0
- * @date 2025/4/15 14:10
- * @description 打卡服务类
+ * @description 打卡结算任务 服务类
+ * @date 2024/11/25 15:12
  */
 @Slf4j
-@Component
+@Service
 public class PunchInManagerImpl implements IPunchInManager {
 
     @Autowired
-    private ICalendarManager calendarManager;
+    private IPunchInService punchInService;
+
+    @Autowired
+    private IPunchInRecordService punchInRecordService;
+
+    @Autowired
+    private ISettleManagerV1 settleManager;
+
+    @Autowired
+    private IPiTaskService piTaskService;
+
+    @Autowired
+    private IPiTaskHistoryService piTaskHistoryService;
+
+    @Autowired
+    private IPunchInCoreManager punchInCoreManager;
+
+    @Autowired
+    private IStatPiTaskYearService statPiTaskYearService;
+
+    @Autowired
+    private IStatPiTaskMonthService statPiTaskMonthService;
+
+    /**
+     * 默认显示时间00:00:00.000
+     */
+    private static final LocalTime DEFAULT_DISPLAY_TIME = LocalTime.parse("00:00:00.000");
+
+    /**
+     * 数值100
+     */
+    private static final BigDecimal ONE_HUNDRED = new BigDecimal(100);
 
     @Override
-    public boolean judgeRepeat(PiTask piTask, String repeatDateStr) {
-        // 每天
-        if (RepeatCategoryEnum.EVERYDAY.equals(piTask.getRepeatCategory())) {
-            return true;
+    public List<PiTaskToDoVO> queryToDoList(Long currentUserId) {
+        Assert.isNull(currentUserId);
+        // 查询打卡任务
+        PiTaskQuery piTaskQuery = new PiTaskQuery();
+        piTaskQuery.setArchiveStatus(ArchiveStatusEnum.ACTIVE);
+        piTaskQuery.setTaskStatus(PunchInTaskStatusEnum.ACTIVE);
+        piTaskQuery.setUserIds(Arrays.asList(currentUserId));
+        List<PiTask> piTasks = piTaskService.queryByCondition(piTaskQuery);
+
+        if (CollectionUtils.isEmpty(piTasks)) {
+            return List.of();
         }
 
-        // 法定工作日
-        if (RepeatCategoryEnum.WORKDAY.equals(piTask.getRepeatCategory())) {
-            return calendarManager.judgeWorkday(repeatDateStr);
-        }
+        // 当前日期
+        LocalDate today = LocalDate.now();
+        String todayStr = DateUtils.YYYY_MM_DD_FORMATTER.format(today);
+        // 当前时间
+        LocalTime nowTime = LocalTime.now();
+        // 打卡任务唯一ID
+        Set<Long> taskUniqueIds = piTasks.stream().map(PiTask::getUniqueId).collect(Collectors.toSet());
+
+        // 查询打卡记录
+        PiTaskHistoryQuery piTaskHistoryQuery = new PiTaskHistoryQuery();
+        piTaskHistoryQuery.setPunchInDate(todayStr);
+        piTaskHistoryQuery.setTaskUniqueIds(taskUniqueIds);
+        piTaskHistoryQuery.setUserIds(Arrays.asList(currentUserId));
+        List<PiTaskHistory> piTaskHistories = piTaskHistoryService.queryByCondition(piTaskHistoryQuery);
+        // 打卡任务唯一ID-打卡记录关联
+        Map<Long, PiTaskHistory> piTaskHistoryMap = piTaskHistories.stream().collect(Collectors.toMap(PiTaskHistory::getTaskUniqueId, Function.identity(), (key1, key2) -> key1));
+
+        // 1.判断重复频率,只显示今天待打卡的任务
+        // 2.判断显示时间,还没到点显示的暂时不显示
+        // 3.根据displayOrder进行排序,按自然顺序排列
+        return piTasks.stream().filter(piTask -> punchInCoreManager.judgeRepeat(piTask, todayStr))
+                .filter(piTask -> {
+                    LocalTime displayTime = Optional.ofNullable(piTask.getDisplayTime()).orElse(DEFAULT_DISPLAY_TIME);
+                    return nowTime.compareTo(displayTime) > -1;
+                })
+                .sorted(Comparator.comparing(piTask -> Optional.ofNullable(piTask.getDisplayOrder()).orElse(0)))
+                .map(piTask -> {
+                    PiTaskToDoVO piTaskToDoVO = new PiTaskToDoVO();
+                    BeanUtils.copyProperties(piTask, piTaskToDoVO);
+                    // 获取并设置已打卡记录
+                    PiTaskHistory piTaskHistory = piTaskHistoryMap.get(piTask.getUniqueId());
+                    if (Objects.nonNull(piTaskHistory)) {
+                        piTaskToDoVO.setCurrentCountTrack(piTaskHistory.getCountTrack());
+                        piTaskToDoVO.setCurrentTimeTrack(piTaskHistory.getTimeTrack());
+                    }
+                    return piTaskToDoVO;
+                }).collect(Collectors.toList());
+    }
 
-        // 法定节假日(含周末)
-        if (RepeatCategoryEnum.HOLIDAY.equals(piTask.getRepeatCategory())) {
-            return calendarManager.judgeHoliday(repeatDateStr);
+    @Override
+    public List<PiTaskSimpleVO> queryTaskList(Long currentUserId) {
+        Assert.isNull(currentUserId);
+        // 查询打卡任务
+        PiTaskQuery piTaskQuery = new PiTaskQuery();
+        piTaskQuery.setArchiveStatus(ArchiveStatusEnum.ACTIVE);
+        piTaskQuery.setTaskStatus(PunchInTaskStatusEnum.ACTIVE);
+        piTaskQuery.setUserIds(Arrays.asList(currentUserId));
+        List<PiTask> piTasks = piTaskService.queryByCondition(piTaskQuery);
+
+        if (CollectionUtils.isEmpty(piTasks)) {
+            return List.of();
         }
 
-        // 自定义
-        if (RepeatCategoryEnum.CUSTOM.equals(piTask.getRepeatCategory())) {
-            if (!StringUtils.hasText(piTask.getRepeatCustomDay())) {
-                BusinessException.throwFail(String.format("打卡任务ID:%s, 重复周期类型:自定义重复,没有设定自定义重复日期"));
-            }
+        // 当前日期
+        LocalDate today = LocalDate.now();
+        String todayStr = DateUtils.YYYY_MM_DD_FORMATTER.format(today);
+        // 获取一周的起始日期范围
+        List<LocalDate> weeklyDateRange = DateUtils.getDateRangeInWeek();
+
+        // 打卡任务唯一ID
+        Set<Long> taskUniqueIds = piTasks.stream().map(PiTask::getUniqueId).collect(Collectors.toSet());
+
+        // 找出范围内的打卡记录
+        PiTaskHistoryQuery piTaskHistoryQuery = new PiTaskHistoryQuery();
+        piTaskHistoryQuery.setTaskUniqueIds(taskUniqueIds);
+        piTaskHistoryQuery.setUserIds(Arrays.asList(currentUserId));
+        piTaskHistoryQuery.setPunchInDateFrom(weeklyDateRange.getFirst().toString());
+        piTaskHistoryQuery.setPunchInDateTo(weeklyDateRange.getLast().toString());
+        List<PiTaskHistory> piTaskHistories = piTaskHistoryService.queryByCondition(piTaskHistoryQuery);
+        // 打卡任务唯一ID-打卡记录关联
+        Map<Long, List<PiTaskHistory>> piTaskHistoryMap = piTaskHistories.stream().collect(Collectors.groupingBy(PiTaskHistory::getTaskUniqueId));
+
+        // 按顺序排列
+        return piTasks.stream()
+                .sorted(Comparator.comparing(piTask -> Optional.ofNullable(piTask.getDisplayOrder()).orElse(0)))
+                .map(piTask -> {
+                    PiTaskSimpleVO piTaskSimpleVO = new PiTaskSimpleVO();
+                    BeanUtils.copyProperties(piTask, piTaskSimpleVO);
+                    // 获取对应的打卡记录
+                    List<PiTaskHistory> tempPiTaskHistories = Optional.ofNullable(piTaskHistoryMap.get(piTask.getUniqueId())).orElse(List.of());
+                    // 任务创建日期
+                    LocalDate creationDate = piTask.getCreationTime().toLocalDateTime().toLocalDate();
+                    // 打卡日期-打卡记录关联
+                    Map<String, PiTaskHistory> tempPiTaskHistoryMap = tempPiTaskHistories.stream().collect(Collectors.toMap(PiTaskHistory::getPunchInDate, Function.identity(), (key1, key2) -> key1));
+                    // 按时间范围遍历,构造页面打卡结果
+                    List<PiTaskHistorySimpleVO> piTaskHistorySimpleVOS = weeklyDateRange.stream().map(punchInDate -> {
+                        // 打卡日期
+                        String punchInDateStr = punchInDate.toString();
+
+                        // 判断页面打卡结果
+                        PiTaskHistory piTaskHistory = tempPiTaskHistoryMap.get(punchInDateStr);
+                        PunchInResultViewEnum punchInResultView = judgePunchInResultView(piTask, piTaskHistory, punchInDate, today, creationDate);
+
+                        // 构建页面打卡结果
+                        PiTaskHistorySimpleVO piTaskHistorySimpleVO = new PiTaskHistorySimpleVO();
+                        piTaskHistorySimpleVO.setPunchInDate(punchInDateStr);
+                        piTaskHistorySimpleVO.setPunchInResult(punchInResultView);
+                        return piTaskHistorySimpleVO;
+                    }).collect(Collectors.toList());
+                    piTaskSimpleVO.setPiTaskHistorySimpleVOS(piTaskHistorySimpleVOS);
+
+                    return piTaskSimpleVO;
+                }).collect(Collectors.toList());
+    }
 
-            LocalDate repeatDate = LocalDate.parse(repeatDateStr);
-            int dayOfWeekValue = repeatDate.getDayOfWeek().getValue();
-            return piTask.getRepeatCustomDay().contains(String.valueOf(dayOfWeekValue));
+    /**
+     * 判断页面打卡结果
+     * @return
+     */
+    private PunchInResultViewEnum judgePunchInResultView(PiTask piTask, PiTaskHistory piTaskHistory, LocalDate punchInDate, LocalDate today, LocalDate creationDate) {
+        // 未到打卡时间
+        if (punchInDate.isAfter(today)) {
+            return PunchInResultViewEnum.FUTURE;
         }
 
-        return false;
-    }
+        // 任务未创建,不需要打卡
+        if (punchInDate.isBefore(creationDate)) {
+            return PunchInResultViewEnum.NOT_NEED;
+        }
 
-    @Override
-    public PunchInResultEnum judgePunchInResultInTask(PiTask piTask, PiTaskHistory piTaskHistory) {
-        Assert.isNullInBusiness(piTask, "打卡任务不能为空 ");
+        // 打卡日期在今天之前且存在打卡记录,则简单判断打卡结果即可
+        if (punchInDate.isBefore(today) && Objects.nonNull(piTaskHistory)) {
+            return PunchInResultEnum.DONE.equals(piTaskHistory.getPunchInResult()) ? PunchInResultViewEnum.DONE : PunchInResultViewEnum.UNDONE;
+        }
 
-        // 没有打卡记录,直接没完成
-        if (Objects.isNull(piTaskHistory)) {
-            return PunchInResultEnum.UNDONE;
+        // 打卡日期在今天之前且不存在打卡记录,则有两种情况:1.那天不用打卡;2.那天需要打卡但是没打卡
+        // TODO 这里应该要有打卡任务的每天记录才能精准判断,现在先简化一下用当前任务的重复频率进行判断
+        if (punchInDate.isBefore(today) && Objects.isNull(piTaskHistory)) {
+            // 判断是否需要打卡
+            boolean repeatResult = punchInCoreManager.judgeRepeat(piTask, today.toString());
+            return repeatResult ? PunchInResultViewEnum.UNDONE : PunchInResultViewEnum.NOT_NEED;
         }
 
-        // 单次打卡,不区分是否节假日
-        if (PunchInMethodEnum.SINGLE.equals(piTask.getPunchInMethod())) {
-            int countTrack = Optional.ofNullable(piTaskHistory.getCountTrack()).orElse(0);
-            return countTrack > 0 ? PunchInResultEnum.DONE : PunchInResultEnum.UNDONE;
+        // 打卡日期是今天,且不存在打卡记录,则有两种情况:1.今天不用打卡;2.今天需要打卡但是还没打卡
+        if (punchInDate.isEqual(today) && Objects.isNull(piTaskHistory)) {
+            // 判断是否需要打卡
+            boolean repeatResult = punchInCoreManager.judgeRepeat(piTask, today.toString());
+            return repeatResult ? PunchInResultViewEnum.UNDONE : PunchInResultViewEnum.NOT_NEED;
         }
 
-        // 打卡任务的节假日启用配置
-        CommonEnableStatusEnum holidayStatus = Optional.ofNullable(piTask.getHolidayStatus()).orElse(CommonEnableStatusEnum.DISABLED);
-        boolean enableHolidayFlag = CommonEnableStatusEnum.ENABLED.equals(holidayStatus) && calendarManager.judgeHoliday(piTaskHistory.getPunchInDate());
+        // 打卡日期是今天,且存在打卡记录,则进一步判断打卡结果
+        if (punchInDate.isEqual(today) && Objects.nonNull(piTaskHistory)) {
+            PunchInResultEnum punchInResult = punchInCoreManager.judgePunchInResultInTask(piTask, piTaskHistory);
+            return PunchInResultEnum.DONE.equals(punchInResult) ? PunchInResultViewEnum.DONE : PunchInResultViewEnum.UNDONE;
+        }
 
-        // 计数打卡,要区分是否节假日使用不同的判断标准
-        if (PunchInMethodEnum.COUNT.equals(piTask.getPunchInMethod())) {
-            int countTrack = enableHolidayFlag ? piTask.getHolidayCountTrack() : piTask.getCountTrack();
-            int punchInCountTrack = Optional.ofNullable(piTaskHistory.getCountTrack()).orElse(0);
-            if (CompareRuleEnum.GTE.equals(piTask.getCompareRule()) && punchInCountTrack >= countTrack) {
-                return PunchInResultEnum.DONE;
+        // 不符合任何情况则是未打卡
+        return PunchInResultViewEnum.NOT_NEED;
+    }
+
+    @Override
+    public PiTaskVO queryTask(Long id) {
+        Assert.isNullInBusiness(id, "请传入待查询的任务ID");
+        return Optional.ofNullable(piTaskService.getById(id)).map(piTask -> {
+            PiTaskVO piTaskVO = new PiTaskVO();
+            BeanUtils.copyProperties(piTask, piTaskVO);
+            return piTaskVO;
+        }).orElseThrow(() -> BusinessException.fail("无法查询到该打卡任务"));
+    }
+
+    @Override
+    public void saveTask(PiTaskRequest request) {
+        Assert.isNullInBusiness(request, "请传入任务信息");
+
+        // 数据校验
+        if (PunchInMethodEnum.TIMING.equals(request.getPunchInMethod())) {
+            if (Objects.isNull(request.getCompareRule()) || Objects.isNull(request.getTimeTrack())) {
+                throw BusinessException.fail("打卡类型:计时,比较规则和时间不能为空");
             }
-            if (CompareRuleEnum.LTE.equals(piTask.getCompareRule()) && punchInCountTrack <= countTrack) {
-                return PunchInResultEnum.DONE;
+            if (CommonEnableStatusEnum.ENABLED.equals(request.getHolidayStatus()) && Objects.isNull(request.getHolidayTimeTrack())) {
+                throw BusinessException.fail("打卡类型:计时,启用了节假日奖励,节假日的时间不能为空");
             }
-            return PunchInResultEnum.UNDONE;
         }
-
-        // 计时打卡,要区分是否节假日使用不同的判断标准
-        if (PunchInMethodEnum.TIMING.equals(piTask.getPunchInMethod())) {
-            LocalTime timeTrack = enableHolidayFlag ? piTask.getHolidayTimeTrack() : piTask.getTimeTrack();
-            LocalTime punchInTimeTrack = Optional.ofNullable(piTaskHistory.getTimeTrack()).orElse(LocalTime.parse("00:00:00.000"));
-            if (CompareRuleEnum.GTE.equals(piTask.getCompareRule()) && punchInTimeTrack.compareTo(timeTrack) > -1) {
-                return PunchInResultEnum.DONE;
+        if (PunchInMethodEnum.COUNT.equals(request.getPunchInMethod())) {
+            if (Objects.isNull(request.getCompareRule()) || Objects.isNull(request.getCountTrack())) {
+                throw BusinessException.fail("打卡类型:计数,比较规则和次数不能为空");
+            }
+            if (CommonEnableStatusEnum.ENABLED.equals(request.getHolidayStatus()) && Objects.isNull(request.getHolidayCountTrack())) {
+                throw BusinessException.fail("打卡类型:计数,启用了节假日奖励,节假日的次数不能为空");
+            }
+        }
+        if (CommonEnableStatusEnum.ENABLED.equals(request.getFullAttendanceStatus()) && (Objects.isNull(request.getFullAttendancePeriod()) || Objects.isNull(request.getFullAttendanceFaultToleranceCnt()))) {
+            throw BusinessException.fail("启用了全勤奖励,全勤周期和全勤容错次数不能为空");
+        }
+        if (RepeatCategoryEnum.CUSTOM.equals(request.getRepeatCategory()) && !StringUtils.hasText(request.getRepeatCustomDay())) {
+            throw BusinessException.fail("自定义重复周期,自定义重复日不能为空");
+        }
+        if (PunchInExtraMethodEnum.FIXED.equals(request.getExtraMethod()) || PunchInExtraMethodEnum.INTERVAL.equals(request.getExtraMethod())) {
+            if (PunchInMethodEnum.TIMING.equals(request.getPunchInMethod()) && Objects.isNull(request.getExtraTimeStep())) {
+                throw BusinessException.fail("打卡类型:计时,额外奖励方式为固定或区间,额外奖励时间间隔不能为空");
+            }
+            if (PunchInExtraMethodEnum.FIXED.equals(request.getExtraMethod()) && Objects.isNull(request.getExtraPoints())) {
+                throw BusinessException.fail("额外奖励方式为固定,额外奖励积分不能为空");
             }
-            if (CompareRuleEnum.LTE.equals(piTask.getCompareRule()) && punchInTimeTrack.compareTo(timeTrack) < 1) {
-                return PunchInResultEnum.DONE;
+            if (PunchInExtraMethodEnum.INTERVAL.equals(request.getExtraMethod()) && CollectionUtils.isEmpty(request.getTaskExtList())) {
+                throw BusinessException.fail("额外奖励方式为区间,积分区间信息不能为空");
             }
+        }
+        if (CommonEnableStatusEnum.ENABLED.equals(request.getContinueStatus()) && (Objects.isNull(request.getGraceDay()) || Objects.isNull(request.getContinueInterruptedCount()) || Objects.isNull(request.getPenaltyDay()))) {
+            throw BusinessException.fail("启用了连续规则,宽限期、连续中断次数、惩罚天数不能为空");
+        }
+        if (CommonEnableStatusEnum.ENABLED.equals(request.getTaskPointsStatus()) && CollectionUtils.isEmpty(request.getContinueTaskExtList())) {
+            throw BusinessException.fail("启用了任务积分计算,连续任务积分区间信息不能为空");
+        }
 
-            return PunchInResultEnum.UNDONE;
+        // 新增打卡任务
+        PiTask addPiTask = new PiTask();
+        BeanUtils.copyProperties(request, addPiTask);
+        addPiTask.setId(null);
+        addPiTask.setTaskStatus(PunchInTaskStatusEnum.ACTIVE);
+        addPiTask.setTaskVersion(0);
+        addPiTask.setArchiveStatus(ArchiveStatusEnum.ACTIVE);
+
+        // 如果任务已存在,则更新任务版本号、设置唯一ID、旧数据归档
+        if (Objects.nonNull(request.getId())) {
+            PiTask piTask = Optional.ofNullable(piTaskService.getById(request.getId())).orElseThrow(() -> BusinessException.fail("无法查询到该打卡任务"));
+            addPiTask.setTaskVersion(piTask.getTaskVersion() + 1);
+            addPiTask.setUniqueId(piTask.getUniqueId());
+
+            // 旧数据归档
+            PiTask updatePiTask = new PiTask();
+            updatePiTask.setId(piTask.getId());
+            updatePiTask.setTaskStatus(PunchInTaskStatusEnum.ARCHIVE);
+            piTaskService.update(updatePiTask);
         }
 
-        return PunchInResultEnum.UNDONE;
+        // 保存数据
+        piTaskService.insert(addPiTask);
+        // 如果首次保存,需要设置唯一ID
+        if (Objects.isNull(addPiTask.getUniqueId())) {
+            PiTask updatePiTask = new PiTask();
+            updatePiTask.setId(addPiTask.getId());
+            updatePiTask.setUniqueId(addPiTask.getId());
+            piTaskService.update(updatePiTask);
+        }
     }
 
     @Override
-    public PunchInResultEnum judgePunchInResultInMultiTask(PiMultiTask piMultiTask, List<PiTaskHistory> piTaskHistoryList) {
-        // 没有打卡记录 或者 没有启用多任务 则直接返回未完成
-        if (CollectionUtils.isEmpty(piTaskHistoryList) || CommonEnableStatusEnum.DISABLED.equals(piMultiTask.getTaskPointsStatus())) {
-            return PunchInResultEnum.UNDONE;
-        }
+    @Transactional(rollbackFor = Exception.class)
+    public void deleteTask(Long id) {
+        Assert.isNullInBusiness(id, "请传入待删除的任务");
 
-        // 完成的打卡数量
-        long punchInDoneCount = piTaskHistoryList.stream().filter(v -> PunchInResultEnum.DONE.equals(v.getPunchInResult())).count();
+        // 新增打卡任务记录
+        PiTask addPiTask = copyAndArchivePiTask(id);
+        addPiTask.setTaskStatus(PunchInTaskStatusEnum.DELETE);
 
-        // 当天打卡次数大于等于设置的次数,则完成打卡
-        // 没有设置时默认设置一个较大的数,避免出现打卡次数为0的情况
-        Integer doneCount = Optional.ofNullable(piMultiTask.getPunchInDoneCount()).orElse(piTaskHistoryList.size() + 1);
-        return punchInDoneCount >= doneCount ? PunchInResultEnum.DONE : PunchInResultEnum.UNDONE;
+        piTaskService.insert(addPiTask);
     }
 
     @Override
-    public int getPunchInTotalCountInRange(RepeatCategoryEnum repeatCategory, String repeatCustomDay, LocalDate repeatStartDate, LocalDate repeatEndDate) {
+    @Transactional(rollbackFor = Exception.class)
+    public void doPunchIn(PunchInRequest request) {
+        if (Objects.isNull(request) || Objects.isNull(request.getId())) {
+            BusinessException.throwFail("请传入待打卡的任务");
+        }
 
-        if (RepeatCategoryEnum.EVERYDAY.equals(repeatCategory)) {
-            return (int) ChronoUnit.DAYS.between(repeatStartDate, repeatEndDate.plusDays(1));
+        PiTask piTask = Optional.ofNullable(piTaskService.getById(request.getId())).orElseThrow(() -> BusinessException.fail("无法查询到该打卡任务"));
+        if (PunchInMethodEnum.TIMING.equals(piTask.getPunchInMethod()) && Objects.isNull(request.getTimeTrack())) {
+            BusinessException.throwFail("打卡类型:计时,请传入时间记录");
         }
 
-        List<LocalDate> dateRange = DateUtils.getDateRange(repeatStartDate, repeatEndDate);
+        // 打卡日期
+        String punchInDate = LocalDate.now().toString();
+
+        // 查询今天的打卡记录
+        PiTaskHistory oldPiTaskHistory = piTaskHistoryService.getByTaskUniqueIdAndPunchInDate(piTask.getUniqueId(), punchInDate);
+
+        // 待更新/新增的打卡记录
+        PiTaskHistory tempPiTaskHistory = new PiTaskHistory();
+        // 不存在则新增,存在则更新
+        if (Objects.isNull(oldPiTaskHistory)) {
+            tempPiTaskHistory.setTaskUniqueId(piTask.getUniqueId());
+            tempPiTaskHistory.setPunchInDate(punchInDate);
+            tempPiTaskHistory.setUserId(UserUtils.getCurrentUserId());
+        } else {
+            tempPiTaskHistory.setId(oldPiTaskHistory.getId());
+        }
+
+        // 打卡类型:单次打卡,
+        if (PunchInMethodEnum.SINGLE.equals(piTask.getPunchInMethod())) {
+            // 需要判断是否重复打卡
+            if (Objects.nonNull(oldPiTaskHistory) && Optional.ofNullable(oldPiTaskHistory.getCountTrack()).orElse(0) > 0) {
+                BusinessException.throwFail("已打卡,无须重复打卡");
+            }
+            // 默认打卡次数是1,是计数打卡的特列
+            tempPiTaskHistory.setCountTrack(1);
+        }
 
-        if (RepeatCategoryEnum.CUSTOM.equals(repeatCategory)) {
-            String[] split = repeatCustomDay.split(",");
-            Set<Integer> customDays = Arrays.stream(split).map(v -> Integer.valueOf(v)).collect(Collectors.toSet());
-            return (int) dateRange.stream().map(v -> v.getDayOfWeek().getValue()).filter(customDays::contains).count();
+        // 打卡类型:计数,需要累加打卡次数
+        if (PunchInMethodEnum.COUNT.equals(piTask.getPunchInMethod())) {
+            tempPiTaskHistory.setCountTrack(Optional.ofNullable(oldPiTaskHistory.getCountTrack()).orElse(0) + 1);
         }
 
-        if (RepeatCategoryEnum.WORKDAY.equals(repeatCategory)) {
-            return (int) dateRange.stream().map(v -> DateUtils.YYYY_MM_DD_FORMATTER.format(v))
-                    .filter(v -> calendarManager.judgeWorkday(v)).count();
+        // 打卡类型:计时,需要记录最新打卡时长
+        if (PunchInMethodEnum.TIMING.equals(piTask.getPunchInMethod())) {
+            tempPiTaskHistory.setTimeTrack(request.getTimeTrack());
         }
 
-        if (RepeatCategoryEnum.HOLIDAY.equals(repeatCategory)) {
-            return (int) dateRange.stream().map(v -> DateUtils.YYYY_MM_DD_FORMATTER.format(v))
-                    .filter(v -> calendarManager.judgeHoliday(v)).count();
+        // 新增或更新
+        if (Objects.isNull(oldPiTaskHistory)) {
+            piTaskHistoryService.insert(tempPiTaskHistory);
+        } else {
+            piTaskHistoryService.update(tempPiTaskHistory);
         }
+    }
 
-        return 0;
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void archiveTask(Long id) {
+        Assert.isNullInBusiness(id, "请传入待删除的任务");
+
+        // 归档
+        PiTask addPiTask = copyAndArchivePiTask(id);
+        addPiTask.setArchiveStatus(ArchiveStatusEnum.ARCHIVE);
+        piTaskService.insert(addPiTask);
     }
 
     @Override
-    public ContinueStageEnum judgeContinueStage(ContinueTask continueTask, PunchInResultEnum punchInResult, PiStatus piStatus, LocalDate punchInDate) {
-        if (CommonEnableStatusEnum.DISABLED.equals(continueTask.getContinueStatus())) {
-            return ContinueStageEnum.NONE;
+    public void remakePunchIn(PunchInRecordRequest request) {
+        // 待补卡的打卡日期
+        LocalDate punchInDate = LocalDate.parse(request.getPunchInDate());
+
+        // 如果补打卡日期是今天,则不允许补卡
+        if (punchInDate.isEqual(LocalDate.now())) {
+            BusinessException.throwFail("补打卡日期不能为今天");
         }
 
-        // TODO 启用/关闭连续打卡规则时要对状态表进行数据初始化
+        // 获取打卡任务
+        PunchIn punchIn = Optional.ofNullable(punchInService.getById(request.getPunchInId()))
+            .orElseThrow(() -> BusinessException.fail("无法查询到该打卡任务"));
+        // 补打卡的打卡日期不能早于打卡任务创建日期
+        if (punchInDate.isBefore(punchIn.getCreationTime().toLocalDateTime().toLocalDate())) {
+            BusinessException.throwFail("补打卡日期不能早于打卡任务创建日期");
+        }
 
-        // 宽限期
-        if (ContinueStageEnum.GRACE_STAGE.equals(piStatus.getContinueStage())) {
-            LocalDate graceDay = piStatus.getStageStartDate().plusDays(continueTask.getGraceDay());
-            // 仍处于宽限期限内
-            if (punchInDate.compareTo(graceDay) <= 0) {
-                return ContinueStageEnum.GRACE_STAGE;
-            }
+        settleManager.settleHandler(PunchInSettleTypeEnum.REMAKE, punchInDate,
+            Arrays.asList(UserUtils.getCurrentUserId()), Arrays.asList(request.getPunchInId()));
+    }
 
-            // 已超过宽限期限,但是未完成打卡
-            if (PunchInResultEnum.UNDONE.equals(punchInResult)) {
-                return ContinueStageEnum.GRACE_STAGE;
-            }
+    @Override
+    public void revokePunchIn(Long id) {
+        // 获取打卡任务
+        PiTask piTask = Optional.ofNullable(piTaskService.getById(id)).orElseThrow(() -> BusinessException.fail("无法查询到该打卡任务"));
+        // 获取打卡记录
+        PiTaskHistory piTaskHistory = piTaskHistoryService.getByTaskUniqueIdAndPunchInDate(piTask.getUniqueId(), LocalDate.now().toString());
 
-            // 已超过宽限期限,且已完成打卡,进入正常打卡期
-            return ContinueStageEnum.NORMAL_STAGE;
+        if (Objects.isNull(piTaskHistory)) {
+            return;
         }
 
-        // 正常打卡期
-        if (ContinueStageEnum.NORMAL_STAGE.equals(piStatus.getContinueStage())) {
-            // 完成打卡则继续是正常打卡期,否则是惩罚期
-            if (PunchInResultEnum.DONE.equals(punchInResult)) {
-                return ContinueStageEnum.NORMAL_STAGE;
-            }
+        PiTaskHistory updatePiTaskHistory = new PiTaskHistory();
+        updatePiTaskHistory.setId(piTaskHistory.getId());
+
+        // 单次打卡,次数置为0
+        if (PunchInMethodEnum.SINGLE.equals(piTask.getPunchInMethod())) {
+            updatePiTaskHistory.setCountTrack(0);
+        }
 
-            // 连续中断次数大于等于设置的中断次数,重新进入宽限期,这里加1是因为需要加上本次的中断次数
-            if (piStatus.getContinueInterruptedCount() + 1 > continueTask.getContinueInterruptedCount()) {
-                return ContinueStageEnum.GRACE_STAGE;
+        // 计时打卡 时间置为00:00:00.000
+        if (PunchInMethodEnum.TIMING.equals(piTask.getPunchInMethod())) {
+            updatePiTaskHistory.setTimeTrack(DEFAULT_DISPLAY_TIME);
+        }
+
+        // 计数打卡,当前打卡次数减1
+        if (PunchInMethodEnum.COUNT.equals(piTask.getPunchInMethod())) {
+            Integer countTrack = Optional.ofNullable(piTaskHistory.getCountTrack()).orElse(0);
+            if (countTrack == 0) {
+                return;
             }
+            updatePiTaskHistory.setCountTrack(countTrack - 1);
+        }
 
-            return ContinueStageEnum.PENALTY_STAGE;
+        // 更新
+        piTaskHistoryService.update(updatePiTaskHistory);
+    }
+
+    @Override
+    public PiTaskStatVO queryStat(PiTaskStatQuery query) {
+        // 当前用户ID
+        Long currentUserId = UserUtils.getCurrentUserId();
+        // 查询统计数据
+        StatPiTask statPiTask = null;
+        if (StatPeriodEnum.YEAR.equals(query.getStatPeriod())) {
+            statPiTask = statPiTaskYearService.getByUserIdAndStatTime(currentUserId, query.getStatTime());
+        } else if (StatPeriodEnum.MONTH.equals(query.getStatPeriod())) {
+            statPiTask = statPiTaskMonthService.getByUserIdAndStatTime(currentUserId, query.getStatTime());
         }
 
-        // 惩罚期
-        if (ContinueStageEnum.PENALTY_STAGE.equals(piStatus.getContinueStage())) {
-            // 仍处于惩罚期
-            if (punchInDate.compareTo(piStatus.getStageEndDate()) <= 0) {
-                return ContinueStageEnum.PENALTY_STAGE;
+        if (Objects.isNull(statPiTask)) {
+            return null;
+        }
+
+        // 查询打卡记录
+        PiTaskHistoryQuery piTaskHistoryQuery = new PiTaskHistoryQuery();
+        piTaskHistoryQuery.setUserIds(Arrays.asList(currentUserId));
+        piTaskHistoryQuery.setPunchInDateLike(query.getStatTime());
+        List<PiTaskHistory> piTaskHistories = piTaskHistoryService.queryByCondition(piTaskHistoryQuery);
+
+        // 查询打卡任务
+        Set<Long> piTaskIds = piTaskHistories.stream().map(PiTaskHistory::getSettlePiTaskId).collect(Collectors.toSet());
+        PiTaskQuery piTaskQuery = new PiTaskQuery();
+        piTaskQuery.setIds(piTaskIds);
+        List<PiTask> piTasks = piTaskService.queryByCondition(piTaskQuery);
+        // 打卡任务ID-打卡任务对象关联
+        Map<Long, PiTask> piTaskMap = piTasks.stream().collect(Collectors.toMap(PiTask::getId, Function.identity(), (key1, key2) -> key1));
+
+        // 组装数据
+        List<PiTaskHistoryStatVO> piTaskHistoryStatVOS = piTaskHistories.stream().map(piTaskHistory -> {
+            PiTaskHistoryStatVO piTaskHistoryStatVO = new PiTaskHistoryStatVO();
+            BeanUtils.copyProperties(piTaskHistory, piTaskHistoryStatVO);
+            return piTaskHistoryStatVO;
+        }).collect(Collectors.toList());
+
+        PiTaskStatVO piTaskStatVO = new PiTaskStatVO();
+        BeanUtils.copyProperties(statPiTask, piTaskStatVO);
+        piTaskStatVO.setPiTaskHistoryStatVOS(piTaskHistoryStatVOS);
+        return piTaskStatVO;
+    }
+    @Override
+    public PunchInDataVO queryPunchInData(PunchInDataQuery query) {
+        PunchIn punchIn = Optional.ofNullable(punchInService.getById(query.getId()))
+            .orElseThrow(() -> BusinessException.fail("找到指定的打卡任务"));
+
+        SimpleDateFormat sdf = DateUtils.buildDateFormat();
+        YearMonth yearMonth = YearMonth.of(query.getYear(), query.getMonth());
+        // 本月第一日
+        LocalDate firstOfMonth = yearMonth.atDay(1);
+        // 本月最后以日
+        LocalDate endOfMonth = yearMonth.atEndOfMonth();
+        // 任务创建日期
+        LocalDate punchInCreationDate = punchIn.getCreationTime().toLocalDateTime().toLocalDate();
+
+        // 获取打卡记录
+        PunchInRecordQuery punchInRecordQuery = new PunchInRecordQuery();
+        punchInRecordQuery.setPunchInId(punchIn.getId());
+        punchInRecordQuery.setStartDate(String.format("%s 00:00:00.000", firstOfMonth));
+        punchInRecordQuery.setEndDate(String.format("%s 23:59:59.999", endOfMonth));
+        List<PunchInRecord> punchInRecords = punchInRecordService.listByCondition(punchInRecordQuery);
+
+        // 构造数据,日历部分的数据只需要已打卡的数据
+        List<PunchInCalendarDataVO> punchInCalendarDataVOS = new ArrayList<>();
+        List<PunchInRecordDataVO> punchInRecordDtoList = new ArrayList<>();
+        for (PunchInRecord punchInRecord : punchInRecords) {
+            PunchInRecordDataVO punchInRecordDataVO = new PunchInRecordDataVO();
+            BeanUtils.copyProperties(punchInRecord, punchInRecordDataVO);
+            punchInRecordDtoList.add(punchInRecordDataVO);
+
+            if (PunchInStatusV1Enum.UN_FINISH.equals(punchInRecord.getPunchInStatus())
+                || PunchInStatusV1Enum.DOING.equals(punchInRecord.getPunchInStatus())) {
+                continue;
             }
+            PunchInCalendarDataVO punchInCalendarDataVO = new PunchInCalendarDataVO();
+            punchInCalendarDataVO.setPunchInDate(punchInRecord.getPunchInDate());
+            punchInCalendarDataVO.setInfo("打卡");
+            punchInCalendarDataVO.setDate(punchInRecord.getPunchInDate());
+            punchInCalendarDataVOS.add(punchInCalendarDataVO);
+        }
 
-            return ContinueStageEnum.NORMAL_STAGE;
+        // 计算全勤率
+        BigDecimal punchInRate = BigDecimal.ZERO;
+        // 要考虑任务刚创建的情况,任务较迟创建的话则使用任务创建时间
+        long dayLength = ChronoUnit.DAYS
+            .between(firstOfMonth.isBefore(punchInCreationDate) ? punchInCreationDate : firstOfMonth, LocalDate.now());
+        if (dayLength != 0) {
+            punchInRate = BigDecimal.valueOf(punchInCalendarDataVOS.size())
+                .divide(BigDecimal.valueOf(dayLength), 4, RoundingMode.HALF_DOWN).multiply(ONE_HUNDRED);
         }
 
-        return ContinueStageEnum.NONE;
+        // 构造返回结果
+        PunchInDataVO punchInDataVO = new PunchInDataVO();
+        punchInDataVO.setStartDate(sdf.format(punchIn.getCreationTime()));
+        punchInDataVO.setEndDate(LocalDate.now().toString());
+        punchInDataVO.setPunchInNum(punchInCalendarDataVOS.size());
+        punchInDataVO.setCalendarSelected(punchInCalendarDataVOS);
+        punchInDataVO.setPunchInRecords(punchInRecordDtoList);
+        punchInDataVO.setPunchInRate(punchInRate);
+
+        return punchInDataVO;
+    }
+
+    /**
+     * 复制打卡任务信息并把旧的信息归档(审计信息不复制、任务版本号自动加1,任务状态:活跃)
+     * @param id 打卡任务id
+     * @return
+     */
+    private PiTask copyAndArchivePiTask(Long id) {
+        // 获取旧的打卡任务信息
+        PiTask oldPiTask = Optional.ofNullable(piTaskService.getById(id)).orElseThrow(() -> BusinessException.fail("打卡任务不存在"));
+
+        // 旧的打卡任务信息归档
+        PiTask updatePiTask = new PiTask();
+        updatePiTask.setId(oldPiTask.getId());
+        updatePiTask.setTaskStatus(PunchInTaskStatusEnum.ARCHIVE);
+        piTaskService.update(updatePiTask);
+
+        // 新的打卡任务信息
+        PiTask piTask = new PiTask();
+        BeanUtils.copyProperties(oldPiTask, piTask);
+        piTask.setId(null);
+        piTask.setCreatedBy(null);
+        piTask.setCreationTime(null);
+        piTask.setLastUpdatedBy(null);
+        piTask.setLastUpdateTime(null);
+        piTask.setVersion(1);
+        piTask.setDeleteFlag(false);
+        piTask.setTaskStatus(PunchInTaskStatusEnum.ACTIVE);
+        piTask.setTaskVersion(Optional.ofNullable(oldPiTask.getTaskVersion()).orElse(0) + 1);
+        return piTask;
     }
 }

+ 0 - 796
src/main/java/com/punchsettle/server/service/manager/impl/PunchInManagerV1Impl.java

@@ -1,796 +0,0 @@
-package com.punchsettle.server.service.manager.impl;
-
-import java.math.BigDecimal;
-import java.math.RoundingMode;
-import java.text.SimpleDateFormat;
-import java.time.LocalDate;
-import java.time.LocalTime;
-import java.time.YearMonth;
-import java.time.temporal.ChronoUnit;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Comparator;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.function.Function;
-import java.util.stream.Collectors;
-
-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.StatPiTaskMonth;
-import com.punchsettle.server.atomic.entity.StatPiTaskWeek;
-import com.punchsettle.server.atomic.entity.PiStatus;
-import com.punchsettle.server.atomic.entity.PiTaskExt;
-import com.punchsettle.server.constant.ContinueStatusEnum;
-import com.punchsettle.server.constant.FullAttendancePeriodEnum;
-import com.punchsettle.server.constant.PunchInDimensionEnum;
-import com.punchsettle.server.constant.PunchInExtraMethodEnum;
-import com.punchsettle.server.constant.RepeatCategoryEnum;
-import com.punchsettle.server.service.manager.ICalendarManager;
-import org.springframework.beans.BeanUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import org.springframework.transaction.annotation.Transactional;
-import org.springframework.util.CollectionUtils;
-
-import com.punchsettle.server.atomic.entity.PunchIn;
-import com.punchsettle.server.atomic.entity.PunchInRecord;
-import com.punchsettle.server.atomic.entity.PiTask;
-import com.punchsettle.server.atomic.entity.PiTaskHistory;
-import com.punchsettle.server.atomic.service.IPunchInRecordService;
-import com.punchsettle.server.atomic.service.IPunchInService;
-import com.punchsettle.server.common.exception.BusinessException;
-import com.punchsettle.server.common.utils.Assert;
-import com.punchsettle.server.common.constant.CommonEnableStatusEnum;
-import com.punchsettle.server.constant.CompareRuleEnum;
-import com.punchsettle.server.constant.PunchInCategoryEnum;
-import com.punchsettle.server.constant.PunchInMethodEnum;
-import com.punchsettle.server.constant.PunchInSettleTypeEnum;
-import com.punchsettle.server.constant.PunchInResultEnum;
-import com.punchsettle.server.constant.PunchInStatusV1Enum;
-import com.punchsettle.server.constant.PunchInStatusViewEnum;
-import com.punchsettle.server.pojo.punchinV1.PunchInCalendarDataVO;
-import com.punchsettle.server.pojo.punchinV1.PunchInDataQuery;
-import com.punchsettle.server.pojo.punchinV1.PunchInDataVO;
-import com.punchsettle.server.pojo.punchinV1.PunchInQuery;
-import com.punchsettle.server.pojo.punchinV1.PunchInRecordDataVO;
-import com.punchsettle.server.pojo.punchinV1.PunchInRecordQuery;
-import com.punchsettle.server.pojo.punchinV1.PunchInRecordRequest;
-import com.punchsettle.server.pojo.punchinV1.PunchInRecordVO;
-import com.punchsettle.server.pojo.punchinV1.PunchInRequest;
-import com.punchsettle.server.pojo.punchinV1.PunchInVO;
-import com.punchsettle.server.pojo.punchinV1.PunchInWithRecordVO;
-import com.punchsettle.server.service.manager.IPunchInManagerV1;
-import com.punchsettle.server.service.manager.ISettleManagerV1;
-import com.punchsettle.server.utiis.DateUtils;
-import com.punchsettle.server.utiis.UserUtils;
-
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.util.StringUtils;
-
-/**
- * @author tyuio
- * @version 1.0.0
- * @description 打卡结算任务 服务类
- * @date 2024/11/25 15:12
- */
-@Slf4j
-@Service
-public class PunchInManagerV1Impl implements IPunchInManagerV1 {
-
-    @Autowired
-    private IPunchInService punchInService;
-
-    @Autowired
-    private IPunchInRecordService punchInRecordService;
-
-    @Autowired
-    private ISettleManagerV1 settleManager;
-
-    /**
-     * 数值100
-     */
-    private static final BigDecimal ONE_HUNDRED = new BigDecimal(100);
-
-    @Override
-    public List<PunchInWithRecordVO> queryPunchInAndRecord() {
-        // 获取当前用户ID
-        Long currentUserId = Optional.ofNullable(UserUtils.getCurrentUserId())
-            .orElseThrow(() -> BusinessException.fail("无法获取当前用户信息,无法查询打卡任务"));
-
-        // 查询打卡任务
-        PunchInQuery punchInQuery = new PunchInQuery();
-        punchInQuery.setArchiveFlag(false);
-        punchInQuery.setUserIds(Arrays.asList(currentUserId));
-        List<PunchIn> punchIns = punchInService.listByCondition(punchInQuery);
-        if (CollectionUtils.isEmpty(punchIns)) {
-            log.info("用户:{} 没有查询到生效的打卡任务");
-            return List.of();
-        }
-
-        // 获取一周的起始日期范围
-        List<LocalDate> weeklyDateRange = DateUtils.getDateRangeInWeek();
-        // 获取打卡任务ID
-        List<Long> punchInIds = punchIns.stream().map(PunchIn::getId).collect(Collectors.toList());
-        // 找出范围内的打卡记录
-        PunchInRecordQuery punchInRecordQuery = new PunchInRecordQuery();
-        punchInRecordQuery.setPunchInIds(punchInIds);
-        punchInRecordQuery.setStartDate(weeklyDateRange.getFirst().toString());
-        punchInRecordQuery.setEndDate(weeklyDateRange.getLast().toString());
-        List<PunchInRecord> punchInRecords = punchInRecordService.listByCondition(punchInRecordQuery);
-
-        // 打卡任务-打卡记录 分组
-        Map<Long, List<PunchInRecord>> recordMap =
-            punchInRecords.stream().collect(Collectors.groupingBy(PunchInRecord::getPunchInId));
-
-        // 日期格式化
-        SimpleDateFormat sdf = DateUtils.buildDateFormat();
-
-        // 当前日期
-        LocalDate today = LocalDate.now();
-
-        // 构建打卡记录
-        List<PunchInWithRecordVO> punchInWithRecordVOS = new ArrayList<>();
-        // 初始化的时间记录
-        LocalTime initRecordTimeTrack = LocalTime.parse("00:00:00.000");
-        for (PunchIn punchIn : punchIns) {
-            // 一周的打卡记录容器
-            List<PunchInRecordVO> weeklyRecords = new ArrayList<>();
-            // 打卡任务信息
-            PunchInWithRecordVO punchInWithRecordVO = new PunchInWithRecordVO();
-            BeanUtils.copyProperties(punchIn, punchInWithRecordVO);
-            punchInWithRecordVO.setPunchInId(punchIn.getId());
-            punchInWithRecordVO.setPunchInRecords(weeklyRecords);
-            punchInWithRecordVO.setRecordTimeTrack(initRecordTimeTrack);
-            punchInWithRecordVO.setRecordCountTrack(0);
-            punchInWithRecordVOS.add(punchInWithRecordVO);
-
-            // 打卡任务创建日期
-            LocalDate punchInCreationDate = LocalDate.parse(sdf.format(punchIn.getCreationTime()));
-
-            // 获取打卡任务对应的打卡记录,并转为打卡日期-打卡记录map
-            List<PunchInRecord> records =
-                Optional.ofNullable(recordMap.get(punchInWithRecordVO.getPunchInId())).orElse(List.of());
-            Map<String, PunchInRecord> weeklyRecordMap = records.stream()
-                .collect(Collectors.toMap(PunchInRecord::getPunchInDate, Function.identity(), (key1, key2) -> key1));
-
-            for (LocalDate weeklyDate : weeklyDateRange) {
-                String weeklyDateStr = weeklyDate.toString();
-
-                // 获取打卡记录
-                PunchInRecord punchInRecord = weeklyRecordMap.get(weeklyDateStr);
-
-                // 根据过往打卡记录设置打卡状态
-                PunchInStatusViewEnum punchInStatus =
-                    judgePunchInStatus(today, weeklyDate, punchInCreationDate, punchIn, punchInRecord);
-
-                // 设置打卡记录
-                PunchInRecordVO punchInRecordVO = new PunchInRecordVO();
-                punchInRecordVO.setPunchInDate(weeklyDateStr);
-                punchInRecordVO.setPunchInStatus(punchInStatus);
-                weeklyRecords.add(punchInRecordVO);
-
-                // 如果是今天的打卡记录,设置计数/计时属性
-                if (!Objects.isNull(punchInRecord) && today.isEqual(weeklyDate)) {
-                    punchInWithRecordVO.setRecordTimeTrack(punchInRecord.getTimeTrack());
-                    punchInWithRecordVO.setRecordCountTrack(punchInRecord.getCountTrack());
-                }
-
-                // 如果是今天设置状态控制页面显示
-                if (today.isEqual(weeklyDate)) {
-                    punchInWithRecordVO.setPunchInStatus(punchInStatus);
-                }
-            }
-        }
-
-        return punchInWithRecordVOS;
-    }
-
-    private PunchInStatusViewEnum judgePunchInStatus(LocalDate today, LocalDate weeklyDate,
-        LocalDate punchInCreationDate, PunchIn punchIn, PunchInRecord punchInRecord) {
-        // 一周某天还没到,无法打卡
-        if (weeklyDate.isAfter(today)) {
-            return PunchInStatusViewEnum.FUTURE_TIME;
-        }
-
-        // 一周某天早于任务创建时间,无法打卡
-        if (weeklyDate.isBefore(punchInCreationDate)) {
-            return PunchInStatusViewEnum.UNCREATED;
-        }
-
-        // 一周某天在今天之前存在打卡记录,则需要判断是否完成打卡
-        if (!Objects.isNull(punchInRecord) && weeklyDate.isBefore(today)) {
-            if (PunchInStatusV1Enum.FINISH.equals(punchInRecord.getPunchInStatus())
-                || PunchInStatusV1Enum.REMAKE_FINISH.equals(punchInRecord.getPunchInStatus())) {
-                return PunchInStatusViewEnum.PUNCH_IN;
-            }
-        }
-
-        // 一周的某天是今天,且存在打卡记录,则判断是否完成打卡
-        if (weeklyDate.isEqual(today) && !Objects.isNull(punchInRecord)) {
-            PunchInStatusV1Enum punchInStatusV1Enum = settleManager.judgePunchInStatus(punchIn, punchInRecord);
-            if (PunchInStatusV1Enum.FINISH.equals(punchInStatusV1Enum)
-                || PunchInStatusV1Enum.REMAKE_FINISH.equals(punchInStatusV1Enum)) {
-                return PunchInStatusViewEnum.PUNCH_IN;
-            }
-            // 当天存在打卡记录,但是还没满足打卡条件,则认为打卡状态未知
-            return PunchInStatusViewEnum.TODAY_UNKNOWN;
-        }
-
-        // 一周的某天是今天,且不存在打卡记录,则还没进行打卡
-        if (weeklyDate.isEqual(today) && Objects.isNull(punchInRecord)) {
-            return PunchInStatusViewEnum.TODAY_UNKNOWN;
-        }
-
-        // 不符合任何情况则是未打卡
-        return PunchInStatusViewEnum.UN_PUNCH_IN;
-    }
-
-    @Override
-    public PunchInVO queryPunchInById(Long punchInId) {
-        Assert.isNullInBusiness(punchInId, "请传入待查询的任务ID");
-        return Optional.ofNullable(punchInService.getById(punchInId)).map(punchIn -> {
-            PunchInVO punchInVO = new PunchInVO();
-            BeanUtils.copyProperties(punchIn, punchInVO);
-            return punchInVO;
-        }).orElseThrow(() -> BusinessException.fail("无法查询到该打卡任务"));
-    }
-
-    @Override
-    public void saveOrUpdatePunchIn(PunchInRequest request) {
-        Assert.isNullInBusiness(request, "请传入任务信息");
-
-        if (PunchInCategoryEnum.COUNT.equals(request.getCategory())
-            && (Objects.isNull(request.getRule()) || Objects.isNull(request.getCountTrack()))) {
-            throw BusinessException.fail("打卡类型:计数,比较规则和次数不能为空");
-        }
-
-        if (PunchInCategoryEnum.TIME.equals(request.getCategory())
-            && (Objects.isNull(request.getRule()) || Objects.isNull(request.getTimeTrack()))) {
-            throw BusinessException.fail("打卡类型:计时,比较规则和时间不能为空");
-        }
-
-        PunchIn punchIn = new PunchIn();
-        BeanUtils.copyProperties(request, punchIn);
-        punchIn.setArchiveFlag(false);
-
-        if (Objects.isNull(punchIn.getId())) {
-            punchInService.insert(punchIn);
-        } else {
-            punchInService.update(punchIn);
-        }
-    }
-
-    @Override
-    public void deletePunchIn(Long punchInId) {
-        Assert.isNullInBusiness(punchInId, "请传入待删除的任务");
-        punchInService.delete(punchInId);
-    }
-
-    @Override
-    @Transactional(rollbackFor = Exception.class)
-    public void doPunchIn(PunchInRequest request) {
-        if (Objects.isNull(request) || Objects.isNull(request.getId())) {
-            BusinessException.throwFail("请传入待打卡的任务");
-        }
-
-        PunchIn punchIn = Optional.ofNullable(punchInService.getById(request.getId()))
-            .orElseThrow(() -> BusinessException.fail("无法查询到该打卡任务"));
-        if (PunchInCategoryEnum.TIME.equals(punchIn.getCategory()) && Objects.isNull(request.getTimeTrack())) {
-            BusinessException.throwFail("打卡类型:计时,请传入时间记录");
-        }
-
-        // 查询今天的打卡记录
-        LocalDate today = LocalDate.now();
-        PunchInRecordQuery punchInRecordQuery = new PunchInRecordQuery();
-        punchInRecordQuery.setPunchInDate(today.toString());
-        punchInRecordQuery.setPunchInId(request.getId());
-        PunchInRecord oldPunchInRecord = punchInRecordService.selectOneByCondition(punchInRecordQuery);
-
-        // 打卡类型:单次打卡,需要判断是否重复打卡
-        if (PunchInCategoryEnum.SINGLE.equals(punchIn.getCategory()) && !Objects.isNull(oldPunchInRecord)) {
-            throw BusinessException.fail("已打卡,无须重复打卡");
-        }
-
-        // 获取或创建打卡记录
-        PunchInRecord punchInRecord = Optional.ofNullable(oldPunchInRecord).orElseGet(() -> {
-            PunchInRecord record = new PunchInRecord();
-            record.setPunchInId(request.getId());
-            record.setPunchInDate(LocalDate.now().toString());
-            return record;
-        });
-
-        // 打卡类型:计数,需要累加打卡次数
-        if (PunchInCategoryEnum.COUNT.equals(punchIn.getCategory())) {
-            punchInRecord.setCountTrack(Optional.ofNullable(punchInRecord.getCountTrack()).orElse(0) + 1);
-        }
-
-        // 打卡类型:计时,需要记录最新打卡时长
-        if (PunchInCategoryEnum.TIME.equals(punchIn.getCategory())) {
-            punchInRecord.setTimeTrack(request.getTimeTrack());
-        }
-
-        // 新增或更新
-        if (Objects.isNull(punchInRecord.getId())) {
-            punchInRecordService.insert(punchInRecord);
-        } else {
-            punchInRecordService.update(punchInRecord);
-        }
-    }
-
-    @Override
-    public void archivePunchIn(Long punchInId) {
-        Assert.isNullInBusiness(punchInId, "请选择待归档的任务");
-
-        PunchIn punchIn = new PunchIn();
-        punchIn.setId(punchInId);
-        punchIn.setArchiveFlag(true);
-        punchInService.update(punchIn);
-    }
-
-    @Override
-    public void remakePunchIn(PunchInRecordRequest request) {
-        // 待补卡的打卡日期
-        LocalDate punchInDate = LocalDate.parse(request.getPunchInDate());
-
-        // 如果补打卡日期是今天,则不允许补卡
-        if (punchInDate.isEqual(LocalDate.now())) {
-            BusinessException.throwFail("补打卡日期不能为今天");
-        }
-
-        // 获取打卡任务
-        PunchIn punchIn = Optional.ofNullable(punchInService.getById(request.getPunchInId()))
-            .orElseThrow(() -> BusinessException.fail("无法查询到该打卡任务"));
-        // 补打卡的打卡日期不能早于打卡任务创建日期
-        if (punchInDate.isBefore(punchIn.getCreationTime().toLocalDateTime().toLocalDate())) {
-            BusinessException.throwFail("补打卡日期不能早于打卡任务创建日期");
-        }
-
-        settleManager.settleHandler(PunchInSettleTypeEnum.REMAKE, punchInDate,
-            Arrays.asList(UserUtils.getCurrentUserId()), Arrays.asList(request.getPunchInId()));
-    }
-
-    @Override
-    public void revokePunchIn(PunchInRecordRequest request) {
-        // 获取打卡任务
-        PunchIn punchIn = Optional.ofNullable(punchInService.getById(request.getPunchInId()))
-            .orElseThrow(() -> BusinessException.fail("无法查询到该打卡任务"));
-
-        PunchInRecordQuery punchInRecordQuery = new PunchInRecordQuery();
-        punchInRecordQuery.setPunchInId(request.getPunchInId());
-        punchInRecordQuery.setPunchInDate(LocalDate.now().toString());
-        PunchInRecord punchInRecord = punchInRecordService.selectOneByCondition(punchInRecordQuery);
-        if (Objects.isNull(punchInRecord)) {
-            log.info("打卡任务:{},打卡日期:{} 没有找到当天打卡记录,进行撤销", punchInRecordQuery.getPunchInId(),
-                punchInRecordQuery.getPunchInDate());
-            return;
-        }
-
-        // 单次打卡/计时打卡 直接删除记录即可
-        if (PunchInCategoryEnum.SINGLE.equals(punchIn.getCategory())
-            || PunchInCategoryEnum.TIME.equals(punchIn.getCategory())) {
-            punchInRecordService.delete(punchInRecord.getId());
-        }
-
-        // 计数打卡,需要减去打卡次数
-        if (PunchInCategoryEnum.COUNT.equals(punchIn.getCategory())
-            && Optional.ofNullable(punchInRecord.getCountTrack()).orElse(0) > 0) {
-            PunchInRecord updateRecord = new PunchInRecord();
-            updateRecord.setId(punchInRecord.getId());
-            updateRecord.setCountTrack(punchInRecord.getCountTrack() - 1);
-            punchInRecordService.update(updateRecord);
-            if (updateRecord.getCountTrack() == 0) {
-                punchInRecordService.delete(punchInRecord.getId());
-            }
-        }
-    }
-
-    @Override
-    public PunchInDataVO queryPunchInData(PunchInDataQuery query) {
-        PunchIn punchIn = Optional.ofNullable(punchInService.getById(query.getId()))
-            .orElseThrow(() -> BusinessException.fail("找到指定的打卡任务"));
-
-        SimpleDateFormat sdf = DateUtils.buildDateFormat();
-        YearMonth yearMonth = YearMonth.of(query.getYear(), query.getMonth());
-        // 本月第一日
-        LocalDate firstOfMonth = yearMonth.atDay(1);
-        // 本月最后以日
-        LocalDate endOfMonth = yearMonth.atEndOfMonth();
-        // 任务创建日期
-        LocalDate punchInCreationDate = punchIn.getCreationTime().toLocalDateTime().toLocalDate();
-
-        // 获取打卡记录
-        PunchInRecordQuery punchInRecordQuery = new PunchInRecordQuery();
-        punchInRecordQuery.setPunchInId(punchIn.getId());
-        punchInRecordQuery.setStartDate(String.format("%s 00:00:00.000", firstOfMonth));
-        punchInRecordQuery.setEndDate(String.format("%s 23:59:59.999", endOfMonth));
-        List<PunchInRecord> punchInRecords = punchInRecordService.listByCondition(punchInRecordQuery);
-
-        // 构造数据,日历部分的数据只需要已打卡的数据
-        List<PunchInCalendarDataVO> punchInCalendarDataVOS = new ArrayList<>();
-        List<PunchInRecordDataVO> punchInRecordDtoList = new ArrayList<>();
-        for (PunchInRecord punchInRecord : punchInRecords) {
-            PunchInRecordDataVO punchInRecordDataVO = new PunchInRecordDataVO();
-            BeanUtils.copyProperties(punchInRecord, punchInRecordDataVO);
-            punchInRecordDtoList.add(punchInRecordDataVO);
-
-            if (PunchInStatusV1Enum.UN_FINISH.equals(punchInRecord.getPunchInStatus())
-                || PunchInStatusV1Enum.DOING.equals(punchInRecord.getPunchInStatus())) {
-                continue;
-            }
-            PunchInCalendarDataVO punchInCalendarDataVO = new PunchInCalendarDataVO();
-            punchInCalendarDataVO.setPunchInDate(punchInRecord.getPunchInDate());
-            punchInCalendarDataVO.setInfo("打卡");
-            punchInCalendarDataVO.setDate(punchInRecord.getPunchInDate());
-            punchInCalendarDataVOS.add(punchInCalendarDataVO);
-        }
-
-        // 计算全勤率
-        BigDecimal punchInRate = BigDecimal.ZERO;
-        // 要考虑任务刚创建的情况,任务较迟创建的话则使用任务创建时间
-        long dayLength = ChronoUnit.DAYS
-            .between(firstOfMonth.isBefore(punchInCreationDate) ? punchInCreationDate : firstOfMonth, LocalDate.now());
-        if (dayLength != 0) {
-            punchInRate = BigDecimal.valueOf(punchInCalendarDataVOS.size())
-                .divide(BigDecimal.valueOf(dayLength), 4, RoundingMode.HALF_DOWN).multiply(ONE_HUNDRED);
-        }
-
-        // 构造返回结果
-        PunchInDataVO punchInDataVO = new PunchInDataVO();
-        punchInDataVO.setStartDate(sdf.format(punchIn.getCreationTime()));
-        punchInDataVO.setEndDate(LocalDate.now().toString());
-        punchInDataVO.setPunchInNum(punchInCalendarDataVOS.size());
-        punchInDataVO.setCalendarSelected(punchInCalendarDataVOS);
-        punchInDataVO.setPunchInRecords(punchInRecordDtoList);
-        punchInDataVO.setPunchInRate(punchInRate);
-
-        return punchInDataVO;
-    }
-
-    /**
-     * 默认打卡完成率
-     */
-    private static final BigDecimal DEFAULT_PUNCH_IN_DONE_RATE = new BigDecimal("101.00");
-
-    @Autowired
-    private ICalendarManager calendarManager;
-
-    @Override
-    public boolean judgeRepeat(PiTask piTask, String repeatDateStr) {
-        // 每天
-        if (RepeatCategoryEnum.EVERYDAY.equals(piTask.getRepeatCategory())) {
-            return true;
-        }
-
-        // 法定工作日
-        if (RepeatCategoryEnum.WORKDAY.equals(piTask.getRepeatCategory())) {
-            return !calendarManager.judgeHoliday(repeatDateStr);
-        }
-
-        // 法定节假日(含周末)
-        if (RepeatCategoryEnum.HOLIDAY.equals(piTask.getRepeatCategory())) {
-            return !calendarManager.judgeHoliday(repeatDateStr);
-        }
-
-        // 自定义
-        if (RepeatCategoryEnum.CUSTOM.equals(piTask.getRepeatCategory())) {
-            if (!StringUtils.hasText(piTask.getRepeatCustomDay())) {
-                BusinessException.throwFail(String.format("打卡任务ID:%s, 重复周期类型:自定义重复,没有设定自定义重复日期"));
-            }
-
-            LocalDate repeatDate = LocalDate.parse(repeatDateStr);
-            int dayOfWeekValue = repeatDate.getDayOfWeek().getValue();
-            return piTask.getRepeatCustomDay().contains(String.valueOf(dayOfWeekValue));
-        }
-
-        return false;
-    }
-
-    @Override
-    public PunchInResultEnum judgePunchInStatusInTask(PiTask piTask, PiTaskHistory piTaskHistory, boolean holidayFlag) {
-        Assert.isNullInBusiness(piTask, "打卡任务不能为空 ");
-        // 没有打卡记录,直接没完成
-        if (Objects.isNull(piTaskHistory)) {
-            return PunchInResultEnum.UNDONE;
-        }
-
-        // 单次打卡,不区分是否节假日
-        if (PunchInMethodEnum.SINGLE.equals(piTask.getPunchInMethod())) {
-            int countTrack = Optional.ofNullable(piTask.getCountTrack()).orElse(0);
-            return countTrack > 0 ? PunchInResultEnum.DONE : PunchInResultEnum.UNDONE;
-        }
-
-        // 打卡任务的节假日启用配置
-        CommonEnableStatusEnum holidayStatus = Optional.ofNullable(piTask.getHolidayStatus()).orElse(CommonEnableStatusEnum.DISABLED);
-        boolean enableHolidayFlag = CommonEnableStatusEnum.ENABLED.equals(holidayStatus) && holidayFlag;
-
-        // 计数打卡,要区分是否节假日使用不同的判断标准
-        if (PunchInMethodEnum.COUNT.equals(piTask.getPunchInMethod())) {
-            int countTrack = enableHolidayFlag ? piTask.getHolidayCountTrack() : piTask.getCountTrack();
-            int punchInCountTrack = Optional.ofNullable(piTaskHistory.getCountTrack()).orElse(0);
-            if (CompareRuleEnum.GTE.equals(piTask.getCompareRule()) && punchInCountTrack >= countTrack) {
-                return PunchInResultEnum.DONE;
-            }
-            if (CompareRuleEnum.LTE.equals(piTask.getCompareRule()) && punchInCountTrack <= countTrack) {
-                return PunchInResultEnum.DONE;
-            }
-            return PunchInResultEnum.UNDONE;
-        }
-
-        // 计时打卡,要区分是否节假日使用不同的判断标准
-        if (PunchInCategoryEnum.TIME.equals(piTask.getPunchInMethod())) {
-            LocalTime timeTrack = enableHolidayFlag ? piTask.getHolidayTimeTrack() : piTask.getTimeTrack();
-            LocalTime punchInTimeTrack = Optional.ofNullable(piTaskHistory.getTimeTrack()).orElse(LocalTime.parse("00:00:00.000"));
-            if (CompareRuleEnum.GTE.equals(piTask.getCompareRule()) && punchInTimeTrack.compareTo(timeTrack) > -1) {
-                return PunchInResultEnum.DONE;
-            }
-            if (CompareRuleEnum.LTE.equals(piTask.getCompareRule()) && punchInTimeTrack.compareTo(timeTrack) < 1) {
-                return PunchInResultEnum.DONE;
-            }
-
-            return PunchInResultEnum.UNDONE;
-        }
-
-        return PunchInResultEnum.UNDONE;
-    }
-
-    @Override
-    public PunchInResultEnum judgePunchInStatusInMultiTask(PiMultiTask piMultiTask, List<PiTaskHistory> piTaskHistoryList, int multiTaskNum) {
-        if (CollectionUtils.isEmpty(piTaskHistoryList) || multiTaskNum == 0) {
-            return PunchInResultEnum.UNDONE;
-        }
-
-        // 完成的打卡数量
-        long punchInDoneCount = piTaskHistoryList.stream().filter(v -> PunchInResultEnum.DONE.equals(v.getPunchInResult())).count();
-
-//        // 次数,当天打卡次数大于等于设置的次数,则完成打卡
-//        if (PunchInMethodMultiEnum.COUNT.equals(punchInMultiTask.getPunchInMethod())) {
-//            // 没有设置时默认设置一个较大的数,避免出现打卡次数为0的情况
-//            Integer doneCount = Optional.ofNullable(punchInMultiTask.getPunchInDoneCount()).orElse(punchInTaskHistoryList.size() + 1);
-//            return punchInDoneCount >= doneCount ? PunchInStatusEnum.DONE : PunchInStatusEnum.UNDONE;
-//        }
-//
-//        // 比率,当天打卡完成比率大于等于设置的比率,则完成打卡
-//
-//        if (PunchInMethodMultiEnum.RATE.equals(punchInMultiTask.getPunchInMethod())) {
-//            // 没有设置时默认设置一个较大的数,避免出现打卡完成率为0的情况
-//            BigDecimal doneRate = Optional.ofNullable(punchInMultiTask.getPunchInDoneRate()).orElse(DEFAULT_PUNCH_IN_DONE_RATE);
-//            BigDecimal punchInDoneRate = BigDecimal.valueOf(punchInDoneCount).divide(BigDecimal.valueOf(multiTaskNum), 2, RoundingMode.HALF_UP);
-//            return punchInDoneRate.compareTo(doneRate) > -1 ? PunchInStatusEnum.DONE : PunchInStatusEnum.UNDONE;
-//        }
-
-        return PunchInResultEnum.UNDONE;
-    }
-
-    @Override
-    public int calculatePointsInTask(PiTask piTask, List<PiTaskExt> piTaskExts, PiTaskHistory piTaskHistory, StatPiTaskWeek statPiTaskWeek, StatPiTaskMonth statPiTaskMonth, PiStatus piStatus) {
-        // 未完成打卡,积分为0
-        if (PunchInResultEnum.UNDONE.equals(piTaskHistory.getPunchInResult())) {
-            return 0;
-        }
-
-        // 单次打卡中使用的拓展信息
-        List<PiTaskExt> punchInExtList = piTaskExts.stream().filter(v -> PunchInDimensionEnum.ONE_DAY.equals(v.getDimension())).collect(Collectors.toList());
-        // 打卡任务使用的拓展信息
-        List<PiTaskExt> piTaskExtList = piTaskExts.stream().filter(v -> PunchInDimensionEnum.MULTI_DAY.equals(v.getDimension())).collect(Collectors.toList());
-
-        // 单个任务积分=基本积分+(可选)额外积分+(可选)连续完成额外积分+法定节假日(含周末)双倍奖励+全勤双倍奖励
-        // 基本积分
-        int basicPoints = Optional.ofNullable(piTask.getPoints()).orElse(0);
-
-        // 额外积分
-        basicPoints += calculateExtraPointsInTask(piTask, punchInExtList, piTaskHistory, calendarManager.judgeHoliday(piTaskHistory.getPunchInDate()));
-
-        // 启用了全勤奖励
-        int fullAttendancePoints = 0;
-        if (CommonEnableStatusEnum.ENABLED.equals(piTask.getFullAttendanceStatus())) {
-            LocalDate punchInDate = LocalDate.parse(piTaskHistory.getPunchInDate());
-            // 结算周期:周,并且结算日是周末,则双倍奖励;
-            if (FullAttendancePeriodEnum.WEEK.equals(piTask.getFullAttendancePeriod()) && punchInDate.getDayOfWeek().getValue() == 7) {
-                int undoneCount = statPiTaskWeek.getPunchInTotalCount() - statPiTaskWeek.getPunchInDoneCount();
-                if (undoneCount <= piTask.getFullAttendanceFaultToleranceCnt()) {
-                    fullAttendancePoints = basicPoints;
-                }
-            }
-
-            // 结算周期:月,结算日是当月最后一天,则双倍奖励;
-            if (FullAttendancePeriodEnum.MONTH.equals(piTask.getFullAttendancePeriod()) && punchInDate.lengthOfMonth() == punchInDate.getDayOfMonth()) {
-                int undoneCount = statPiTaskMonth.getPunchInTotalCount() - statPiTaskMonth.getPunchInDoneCount();
-                if (undoneCount <= piTask.getFullAttendanceFaultToleranceCnt()) {
-                    fullAttendancePoints = basicPoints;
-                }
-            }
-        }
-
-        // 启用了法定节假日(含周末)双倍奖励
-        int holidayPoints = 0;
-        if (CommonEnableStatusEnum.ENABLED.equals(piTask.getHolidayStatus()) && calendarManager.judgeHoliday(piTaskHistory.getPunchInDate())) {
-            holidayPoints = basicPoints;
-        }
-
-        // 连续完成额外积分
-        int taskPoints = 0;
-        if (CommonEnableStatusEnum.ENABLED.equals(piTask.getTaskPointsStatus()) && ContinueStatusEnum.CONTINUE.equals(piStatus.getTaskContinueStatus())) {
-            // punchInTaskExtList 根据InitialValue倒序排列
-            piTaskExtList.sort(Comparator.comparing(PiTaskExt::getInitialValue).reversed());
-            // 第二轮标志
-            boolean secondRound = false;
-            // 上一轮的值
-            int prevInitialValue = 0;
-            for (PiTaskExt piTaskExt : piTaskExtList) {
-                // 比较结果
-                int compareValue = piStatus.getTaskContinueDay().compareTo(piTaskExt.getInitialValue());
-                // 如果连续日期小于initialValue,则跳过
-                if (compareValue == -1) {
-                    continue;
-                }
-                // 额外奖励数
-                int extraCount = 0;
-                // 如果连续日期大于等于initialValue,则进行第一次计算,并把第二轮标志位设置为true,第二轮/后续轮只需要用上一轮的值进行计算
-                if (secondRound) {
-                    extraCount = prevInitialValue - piTaskExt.getInitialValue();
-                } else if (compareValue >= 0) {
-                    extraCount = piStatus.getTaskContinueDay() - piTaskExt.getInitialValue() + 1;
-                    secondRound = true;
-                }
-                taskPoints +=  piTaskExt.getExtraPoints() * extraCount;
-                prevInitialValue = piTaskExt.getInitialValue();
-            }
-        }
-
-        return basicPoints + fullAttendancePoints + holidayPoints + taskPoints;
-    }
-
-    /**
-     * 计算额外积分
-     * @param piTask
-     * @param piTaskExtList
-     * @return
-     */
-    private int calculateExtraPointsInTask(PiTask piTask, List<PiTaskExt> piTaskExtList, PiTaskHistory piTaskHistory, boolean holidayFlag) {
-        // 单次打卡或者没有启用额外积分计算则跳过
-        if (PunchInExtraMethodEnum.NONE.equals(piTask.getExtraMethod())
-            || PunchInMethodEnum.SINGLE.equals(piTask.getPunchInMethod())) {
-            return 0;
-        }
-
-        // 计算超出部分,
-        int extraCountTrack = 0;
-        // 计数打卡
-        if (PunchInMethodEnum.COUNT.equals(piTask.getPunchInMethod())) {
-            extraCountTrack = piTaskHistory.getCountTrack() - (holidayFlag ? piTask.getHolidayCountTrack() : piTask.getCountTrack());
-        }
-        // 计时打卡
-        if (PunchInMethodEnum.TIMING.equals(piTask.getPunchInMethod())) {
-            // 超出的时间按照时间间隔转换成次数
-            long timeTrack = piTaskHistory.getTimeTrack().until((holidayFlag ? piTask.getHolidayTimeTrack() : piTask.getTimeTrack()), ChronoUnit.MINUTES);
-            extraCountTrack = BigDecimal.valueOf(timeTrack).divide(BigDecimal.valueOf(piTask.getExtraTimeStep()), 0, RoundingMode.FLOOR).intValue();
-        }
-
-        // 如果等于0则没有超出部分,不用计算
-        if (extraCountTrack == 0) {
-            return 0;
-        }
-
-        // 固定计算
-        if (PunchInExtraMethodEnum.FIXED.equals(piTask.getExtraMethod())) {
-            Integer extraPoints = Optional.ofNullable(piTask.getExtraPoints()).orElse(0);
-            return extraCountTrack * extraPoints;
-        }
-
-        // 区间计算
-        if (PunchInExtraMethodEnum.INTERVAL.equals(piTask.getExtraMethod()) && !CollectionUtils.isEmpty(piTaskExtList)) {
-            int basicPoints = 0;
-            int prevInitialValue = 0;
-            for (PiTaskExt piTaskExt : piTaskExtList) {
-                Integer initialValue = Optional.ofNullable(piTaskExt.getInitialValue()).orElse(0);
-                // 第一轮:initialValue - extraCountTrack的值v1
-                // 如果v1≤0则超出initialValue范围,使用initialValue计算;
-                // 如果v1>0则在initialValue范围内 使用extraCountTrack
-                // 后续轮:本轮initialValue - extraCountTrack的值v1、
-                // 如果v1≤0则超出本轮initialValue范围,使用上一轮initialValue-本轮initialValue的值v2计算;
-                // 如果v1>0则在本轮initialValue范围内 使用extraCountTrack-上一轮initialValue的值v3计算
-                // 下面的代码不适合第一轮的计算
-                if (initialValue - extraCountTrack <= 0) {
-                    basicPoints = piTaskExt.getExtraPoints() * Math.abs(prevInitialValue - initialValue);
-                } else {
-                    basicPoints = piTaskExt.getExtraPoints() * (extraCountTrack - prevInitialValue);
-                }
-                prevInitialValue = initialValue;
-            }
-            return basicPoints;
-        }
-
-        return 0;
-    }
-
-    @Override
-    public int calculatePointsInMultiTask(PiMultiTask piMultiTask, List<PiMultiTaskExt> piMultiTaskExts, PiMultiTaskHistory piMultiTaskHistory, PiStatus piStatus) {
-        // 未完成打卡或没有启用多任务积分计算,积分为0
-        if (PunchInResultEnum.UNDONE.equals(piMultiTaskHistory.getPunchInResult())
-            || CommonEnableStatusEnum.ENABLED.equals(piMultiTask.getTaskPointsStatus())) {
-            return 0;
-        }
-
-        // 单次打卡中使用的拓展信息
-        List<PiMultiTaskExt> punchInExtList = piMultiTaskExts.stream().filter(v -> PunchInDimensionEnum.ONE_DAY.equals(v.getDimension())).collect(Collectors.toList());
-        // 打卡任务使用的拓展信息
-        List<PiMultiTaskExt> punchInTaskExtList = piMultiTaskExts.stream().filter(v -> PunchInDimensionEnum.MULTI_DAY.equals(v.getDimension())).collect(Collectors.toList());
-
-        // 多个任务积分=多任务基本积分+多任务额外积分+连续完成额外积分
-        // 基本积分
-        int basicPoints = piMultiTask.getPoints();
-
-        // 额外积分
-        int extraPoints = 0;
-        // 额外次数
-        int extractCount = piMultiTaskHistory.getPunchInDoneCount() - piMultiTask.getPunchInDoneCount();
-        // 固定计算
-        if (PunchInExtraMethodEnum.FIXED.equals(piMultiTask.getExtraMethod())) {
-            extraPoints = extractCount * piMultiTask.getExtraPoints();
-        }
-        // 区间计算
-        if (PunchInExtraMethodEnum.INTERVAL.equals(piMultiTask.getExtraMethod()) && !CollectionUtils.isEmpty(piMultiTaskExts)) {
-            // punchInTaskExtList 根据InitialValue倒序排列
-            punchInExtList.sort(Comparator.comparing(PiMultiTaskExt::getInitialValue).reversed());
-            // 第二轮标志
-            boolean secondRound = false;
-            // 上一轮的值
-            int prevInitialValue = 0;
-            for (PiMultiTaskExt punchInTaskExt : punchInTaskExtList) {
-                // 比较结果
-                int compareValue = Integer.compare(extractCount, punchInTaskExt.getInitialValue());
-                // 如果连续日期小于initialValue,则跳过
-                if (compareValue == -1) {
-                    continue;
-                }
-                // 额外奖励数
-                int tempExtraCount = 0;
-                // 如果连续日期大于等于initialValue,则进行第一次计算,并把第二轮标志位设置为true,第二轮/后续轮只需要用上一轮的值进行计算
-                if (secondRound) {
-                    tempExtraCount = prevInitialValue - punchInTaskExt.getInitialValue();
-                } else if (compareValue >= 0) {
-                    tempExtraCount = extractCount - punchInTaskExt.getInitialValue() + 1;
-                    secondRound = true;
-                }
-                extraPoints +=  punchInTaskExt.getExtraPoints() * tempExtraCount;
-                prevInitialValue = punchInTaskExt.getInitialValue();
-            }
-        }
-
-        // 连续完成额外积分
-        int taskPoints = 0;
-        if (CommonEnableStatusEnum.ENABLED.equals(piMultiTask.getTaskPointsStatus()) && ContinueStatusEnum.CONTINUE.equals(piStatus.getTaskContinueStatus())) {
-            // punchInTaskExtList 根据InitialValue倒序排列
-            punchInTaskExtList.sort(Comparator.comparing(PiMultiTaskExt::getInitialValue).reversed());
-            // 第二轮标志
-            boolean secondRound = false;
-            // 上一轮的值
-            int prevInitialValue = 0;
-            for (PiMultiTaskExt punchInTaskExt : punchInTaskExtList) {
-                // 比较结果
-                int compareValue = piStatus.getTaskContinueDay().compareTo(punchInTaskExt.getInitialValue());
-                // 如果连续日期小于initialValue,则跳过
-                if (compareValue == -1) {
-                    continue;
-                }
-                // 额外奖励数
-                int tempExtraCount = 0;
-                // 如果连续日期大于等于initialValue,则进行第一次计算,并把第二轮标志位设置为true,第二轮/后续轮只需要用上一轮的值进行计算
-                if (secondRound) {
-                    tempExtraCount = prevInitialValue - punchInTaskExt.getInitialValue();
-                } else if (compareValue >= 0) {
-                    tempExtraCount = piStatus.getTaskContinueDay() - punchInTaskExt.getInitialValue() + 1;
-                    secondRound = true;
-                }
-                taskPoints +=  punchInTaskExt.getExtraPoints() * tempExtraCount;
-                prevInitialValue = punchInTaskExt.getInitialValue();
-            }
-        }
-
-        return basicPoints + extraPoints + taskPoints;
-    }
-}

+ 5 - 4
src/main/java/com/punchsettle/server/service/manager/impl/PunchInSettleManagerImpl.java

@@ -19,6 +19,7 @@ import com.punchsettle.server.atomic.entity.AccountTransferHistory;
 import com.punchsettle.server.atomic.service.IAccountService;
 import com.punchsettle.server.atomic.service.IAccountTransferHistoryService;
 import com.punchsettle.server.constant.AccountCategoryEnum;
+import com.punchsettle.server.constant.PunchInTaskStatusEnum;
 import com.punchsettle.server.constant.TransferCategoryEnum;
 import com.punchsettle.server.pojo.punchIn.AccountQuery;
 import org.springframework.beans.BeanUtils;
@@ -68,7 +69,7 @@ import com.punchsettle.server.pojo.punchIn.PiTaskHistoryQuery;
 import com.punchsettle.server.pojo.punchIn.PiTaskQuery;
 import com.punchsettle.server.pojo.punchIn.PunchInSettleData;
 import com.punchsettle.server.service.manager.ICalendarManager;
-import com.punchsettle.server.service.manager.IPunchInManager;
+import com.punchsettle.server.service.manager.IPunchInCoreManager;
 import com.punchsettle.server.service.manager.IPunchInSettleManager;
 import com.punchsettle.server.service.manager.ISettleManager;
 import com.punchsettle.server.utiis.DateUtils;
@@ -138,7 +139,7 @@ public class PunchInSettleManagerImpl implements IPunchInSettleManager {
     private ISettlePointsHistoryService settlePointsHistoryService;
 
     @Autowired
-    private IPunchInManager punchInManager;
+    private IPunchInCoreManager punchInManager;
 
     @Autowired
     private ISettleManager settleManager;
@@ -393,7 +394,7 @@ public class PunchInSettleManagerImpl implements IPunchInSettleManager {
 
         // 获取多任务信息,用户ID-多任务关联
         PiMultiTaskQuery piMultiTaskQuery = new PiMultiTaskQuery();
-        piMultiTaskQuery.setMultiTaskTaskStatus(ArchiveStatusEnum.ACTIVE);
+        piMultiTaskQuery.setMultiTaskTaskStatus(PunchInTaskStatusEnum.ACTIVE);
         piMultiTaskQuery.setUserIds(userIds);
         List<PiMultiTask> piMultiTasks = piMultiTaskService.queryByCondition(piMultiTaskQuery);
         Map<Long, PiMultiTask> piMultiTaskMap = piMultiTasks.stream()
@@ -436,7 +437,7 @@ public class PunchInSettleManagerImpl implements IPunchInSettleManager {
 
         // 获取打卡任务信息,打卡任务唯一ID-打卡任务关联
         PiTaskQuery piTaskQuery = new PiTaskQuery();
-        piTaskQuery.setTaskStatus(ArchiveStatusEnum.ACTIVE);
+        piTaskQuery.setTaskStatus(PunchInTaskStatusEnum.ACTIVE);
         piTaskQuery.setArchiveStatus(ArchiveStatusEnum.ACTIVE);
         piTaskQuery.setUserIds(userIds);
         List<PiTask> piTasks = piTaskService.queryByCondition(piTaskQuery);

+ 0 - 60
src/main/java/com/punchsettle/server/task/PunchInCoreTask.java

@@ -1,67 +1,7 @@
 package com.punchsettle.server.task;
 
-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.PiStatusHistory;
-import com.punchsettle.server.atomic.entity.PiTask;
-import com.punchsettle.server.atomic.entity.PiTaskExt;
-import com.punchsettle.server.atomic.entity.PiTaskHistory;
-import com.punchsettle.server.atomic.entity.SettlePointsHistory;
-import com.punchsettle.server.atomic.entity.StatPiTaskMonth;
-import com.punchsettle.server.atomic.entity.StatPiTaskWeek;
-import com.punchsettle.server.atomic.entity.User;
-import com.punchsettle.server.atomic.service.IPiMultiTaskExtService;
-import com.punchsettle.server.atomic.service.IPiMultiTaskHistoryService;
-import com.punchsettle.server.atomic.service.IPiMultiTaskRelaService;
-import com.punchsettle.server.atomic.service.IPiMultiTaskService;
-import com.punchsettle.server.atomic.service.IPiStatusHistoryService;
-import com.punchsettle.server.atomic.service.ISettlePointsHistoryService;
-import com.punchsettle.server.atomic.service.IStatPiTaskMonthService;
-import com.punchsettle.server.atomic.service.IStatPiTaskWeekService;
-import com.punchsettle.server.atomic.service.IPiStatusService;
-import com.punchsettle.server.atomic.service.IPiTaskExtService;
-import com.punchsettle.server.atomic.service.IPiTaskHistoryService;
-import com.punchsettle.server.atomic.service.IPiTaskService;
-import com.punchsettle.server.atomic.service.IUserService;
-import com.punchsettle.server.constant.ArchiveStatusEnum;
-import com.punchsettle.server.constant.ContinueStageEnum;
-import com.punchsettle.server.constant.ContinueStatusEnum;
-import com.punchsettle.server.constant.PunchInResultEnum;
-import com.punchsettle.server.constant.SettleResultEnum;
-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.PunchInSettleData;
-import com.punchsettle.server.pojo.punchIn.PiStatusQuery;
-import com.punchsettle.server.pojo.punchIn.PiTaskData;
-import com.punchsettle.server.pojo.punchIn.PiTaskExtQuery;
-import com.punchsettle.server.pojo.punchIn.PiTaskHistoryQuery;
-import com.punchsettle.server.pojo.punchIn.PiTaskQuery;
-import com.punchsettle.server.service.manager.ICalendarManager;
-import com.punchsettle.server.service.manager.IPunchInManager;
-import com.punchsettle.server.service.manager.ISettleManager;
-import com.punchsettle.server.utiis.DateUtils;
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.BeanUtils;
-import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
-import org.springframework.util.CollectionUtils;
-
-import java.math.BigDecimal;
-import java.math.RoundingMode;
-import java.time.DayOfWeek;
-import java.time.LocalDate;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.Set;
-import java.util.function.Function;
-import java.util.stream.Collectors;
 
 /**
  * @author tyuio

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

@@ -22,7 +22,7 @@ import com.punchsettle.server.constant.ContinueStageEnum;
 import com.punchsettle.server.constant.PunchInMethodEnum;
 import com.punchsettle.server.constant.PunchInResultEnum;
 import com.punchsettle.server.constant.RepeatCategoryEnum;
-import com.punchsettle.server.service.manager.IPunchInManager;
+import com.punchsettle.server.service.manager.IPunchInCoreManager;
 
 /**
  * @author tyuio
@@ -35,7 +35,7 @@ import com.punchsettle.server.service.manager.IPunchInManager;
 class PunchInManagerImplTest {
 
     @Autowired
-    private IPunchInManager punchInManager;
+    private IPunchInCoreManager punchInManager;
 
     @Test
     void judgeRepeat() {