Просмотр исходного кода

【feat】【v3】
1.完善结算逻辑

ChenYL 11 месяцев назад
Родитель
Сommit
9192f2ac25
28 измененных файлов с 601 добавлено и 213 удалено
  1. 11 0
      doc/sql/update-v3.sql
  2. 82 65
      doc/技术文档.md
  3. 3 1
      src/main/java/com/punchsettle/server/atomic/entity/PiMultiTaskHistory.java
  4. 38 0
      src/main/java/com/punchsettle/server/atomic/entity/PiStatus.java
  5. 44 0
      src/main/java/com/punchsettle/server/atomic/entity/PiStatusHistory.java
  6. 3 3
      src/main/java/com/punchsettle/server/atomic/entity/PiTaskHistory.java
  7. 2 1
      src/main/java/com/punchsettle/server/atomic/mapper/PiStatusHistoryMapper.java
  8. 2 1
      src/main/java/com/punchsettle/server/atomic/mapper/PiStatusMapper.java
  9. 2 1
      src/main/java/com/punchsettle/server/atomic/mapper/StatPiTaskMonthMapper.java
  10. 2 1
      src/main/java/com/punchsettle/server/atomic/mapper/StatPiTaskWeekMapper.java
  11. 10 0
      src/main/java/com/punchsettle/server/atomic/service/IPiStatusHistoryService.java
  12. 6 0
      src/main/java/com/punchsettle/server/atomic/service/IPiStatusService.java
  13. 6 0
      src/main/java/com/punchsettle/server/atomic/service/IStatPiTaskMonthService.java
  14. 6 0
      src/main/java/com/punchsettle/server/atomic/service/IStatPiTaskWeekService.java
  15. 1 1
      src/main/java/com/punchsettle/server/atomic/service/impl/PiMultiTaskRelaServiceImpl.java
  16. 15 0
      src/main/java/com/punchsettle/server/atomic/service/impl/PiStatusHistoryServiceImpl.java
  17. 7 1
      src/main/java/com/punchsettle/server/atomic/service/impl/PiStatusServiceImpl.java
  18. 1 1
      src/main/java/com/punchsettle/server/atomic/service/impl/PiTaskExtServiceImpl.java
  19. 3 0
      src/main/java/com/punchsettle/server/atomic/service/impl/PiTaskServiceImpl.java
  20. 6 0
      src/main/java/com/punchsettle/server/atomic/service/impl/StatPiTaskMonthServiceImpl.java
  21. 6 0
      src/main/java/com/punchsettle/server/pojo/punchIn/PiTaskQuery.java
  22. 7 12
      src/main/java/com/punchsettle/server/service/manager/IPunchInManager.java
  23. 9 45
      src/main/java/com/punchsettle/server/service/manager/impl/PunchInManagerImpl.java
  24. 3 3
      src/main/java/com/punchsettle/server/service/manager/impl/PunchInManagerV1Impl.java
  25. 1 1
      src/main/java/com/punchsettle/server/service/manager/impl/SettleManagerImpl.java
  26. 6 0
      src/main/java/com/punchsettle/server/service/manager/impl/StatPiTaskWeekServiceImpl.java
  27. 243 59
      src/main/java/com/punchsettle/server/task/PunchInCoreTask.java
  28. 76 17
      src/main/java/com/punchsettle/server/utiis/DateUtils.java

+ 11 - 0
doc/sql/update-v3.sql

@@ -363,6 +363,11 @@ CREATE TABLE `pi_status` (
   `stage_start_date` date DEFAULT NULL COMMENT '阶段开始日期',
   `stage_end_date` date DEFAULT NULL COMMENT '阶段结束日期',
   `continue_interrupted_count` int DEFAULT NULL COMMENT '连续中断次数',
+  `repeat_category` varchar(10) DEFAULT NULL COMMENT '重复周期类型(每日-EVERYDAY、法定工作日-WORKDAY、法定节假日(含周末)-HOLIDAY、自定义(周一至周日)-CUSTOM)',
+  `repeat_custom_day` varchar(13) DEFAULT NULL COMMENT '自定义重复日(周一-1,周二-2,周三-3,周四-4,周五-5,周六-6,周日-7)',
+  `repeat_start_date` date DEFAULT NULL COMMENT '重复周期开始时间',
+  `repeat_prev_total_count_in_week` int NOT NULL COMMENT '本周需打卡数(变更重复类型前)',
+  `repeat_prev_total_count_in_month` int NOT NULL COMMENT '本月需打卡数(变更重复类型前)',
   `stat_time_in_week` char(8) NOT NULL COMMENT '统计周数(格式:yyyy-周数)',
   `punch_in_total_count_in_week` int NOT NULL COMMENT '本周需打卡数',
   `punch_in_count_in_week` int NOT NULL COMMENT '本周已打卡数',
@@ -397,6 +402,12 @@ CREATE TABLE `pi_status_history` (
   `stage_start_date` date DEFAULT NULL COMMENT '阶段开始日期',
   `stage_end_date` date DEFAULT NULL COMMENT '阶段结束日期',
   `continue_interrupted_count` int DEFAULT NULL COMMENT '连续中断次数',
+  `repeat_category` varchar(10) DEFAULT NULL COMMENT '重复周期类型(每日-EVERYDAY、法定工作日-WORKDAY、法定节假日(含周末)-HOLIDAY、自定义(周一至周日)-CUSTOM)',
+  `repeat_custom_day` varchar(13) DEFAULT NULL COMMENT '自定义重复日(周一-1,周二-2,周三-3,周四-4,周五-5,周六-6,周日-7)',
+  `repeat_start_date_in_week` date DEFAULT NULL COMMENT '本周重复周期开始时间',
+  `repeat_prev_total_count_in_week` int NOT NULL COMMENT '本周需打卡数(变更重复类型前)',
+  `repeat_start_date_in_month` date DEFAULT NULL COMMENT '本月重复周期开始时间',
+  `repeat_prev_total_count_in_month` int NOT NULL COMMENT '本月需打卡数(变更重复类型前)',
   `stat_time_in_week` char(8) NOT NULL COMMENT '统计周数(格式:yyyy-周数)',
   `punch_in_total_count_in_week` int NOT NULL COMMENT '本周需打卡数',
   `punch_in_count_in_week` int NOT NULL COMMENT '本周已打卡数',

+ 82 - 65
doc/技术文档.md

@@ -156,9 +156,16 @@ ui设计工具:即时设计
 **对本周/本月的总打卡次数影响:**
 
 * 如果不更换:只有1个总打卡次数
-
 * 如果更换:总打卡次数=重复类型A范围的总次数+重复类型B范围的总次数+重复类型C范围的总次数.....
 
+**计算公式:**总打卡次数=历史真实发生的总打卡次数+上次发生的总打卡次数+本次可能的总打卡次数
+
+| 变换时间点 | 重复类型 | 周一 | 周二 | 周三 | 周四 | 周五 | 周六 | 周日 | 总打卡次数 |
+| ---------- | -------- | ---- | ---- | ---- | ---- | ---- | ---- | ---- | ---------- |
+| 周一       | 每天     | ✅    | ✅    | ✅    | ✅    | ✅    | ✅    | ✅    | 7          |
+| 周三       | 自定义1  |      |      | ✅    |      |      | ✅    | ✅    | 5=2+3+0    |
+| 周六       | 自定义2  |      |      |      |      |      |      | ✅    | 4=2+1+1    |
+
 **对全勤结算的影响:**
 
 * 全勤周期类型:每周、每月
@@ -797,37 +804,43 @@ ui设计工具:即时设计
 
 作用:multi_task_unique_id和task_unique_id字段不能同时出现,是一张公用表,multi_task_unique_id出现时是多任务的打卡状态,task_unique_id出现时是单任务的打卡状态
 
-| 字段                          | 类型        | 描述                                                         | 索引     |
-| ----------------------------- | ----------- | ------------------------------------------------------------ | -------- |
-| id                            | bigint      | 主键                                                         | 主键索引 |
-| user_id                       | bigint      | 用户ID                                                       | 普通索引 |
-| multi_task_unique_id          | bigint      | 打卡多任务唯一ID                                             | 普通索引 |
-| multi_task_id                 | bigint      | 打卡多任务ID                                                 |          |
-| task_unique_id                | bigint      | 打卡任务唯一ID                                               | 普通索引 |
-| taks_id                       | bigint      | 打卡任务ID                                                   |          |
-| status_date                   | date        | 记录状态的时间                                               |          |
-| task_continue_status          | varchar(20) | 任务连续打卡状态(连续打卡-CONTINUE、中断-INTERRUPTED)        |          |
-| task_continue_day             | int         | 任务连续天数,第一天开始就等于1                              |          |
-| continue_stage                | varchar(10) | 连续阶段(宽限期-GRACE_STAGE,正常打卡期-NORMAL_STAGE,惩罚期-PENALTY_STAGE) |          |
-| stage_start_date              | date        | 阶段开始日期                                                 |          |
-| stage_end_date                | date        | 阶段结束日期                                                 |          |
-| continue_interrupted_count    | int         | 连续中断次数                                                 |          |
-| stat_time_in_week             | char(8)     | 本周时间(格式:yyyy-W周数)                                 |          |
-| punch_in_total_count_in_week  | int         | 本周需打卡数                                                 |          |
-| punch_in_count_in_week        | int         | 本周已打卡数                                                 |          |
-| punch_in_done_count_in_week   | int         | 本周完成打卡数                                               |          |
-| points_in_week                | int         | 本周获取积分数                                               |          |
-| stat_time_in_month            | char(7)     | 本月时间(格式:yyyy-MM)                                    |          |
-| punch_in_total_count_in_month | int         | 本月需打卡数                                                 |          |
-| punch_in_count_in_month       | int         | 本月已打卡数                                                 |          |
-| punch_in_done_count_in_month  | int         | 本月完成打卡数                                               |          |
-| points_in_month               | int         | 本月获取积分数                                               |          |
-| created_by                    | bigint      | 创建人                                                       |          |
-| creation_time                 | timestamp   | 创建时间                                                     |          |
-| last_updated_by               | bigint      | 最后更新人                                                   |          |
-| last_update_time              | timestamp   | 最后更新时间                                                 |          |
-| version                       | bigint      | 版本号                                                       |          |
-| delete_flag                   | tinyint     | 逻辑删除标志(0-未删除,1-已删除)                           |          |
+| 字段                             | 类型        | 描述                                                         | 索引     |
+| -------------------------------- | ----------- | ------------------------------------------------------------ | -------- |
+| id                               | bigint      | 主键                                                         | 主键索引 |
+| user_id                          | bigint      | 用户ID                                                       | 普通索引 |
+| multi_task_unique_id             | bigint      | 打卡多任务唯一ID                                             | 普通索引 |
+| multi_task_id                    | bigint      | 打卡多任务ID                                                 |          |
+| task_unique_id                   | bigint      | 打卡任务唯一ID                                               | 普通索引 |
+| taks_id                          | bigint      | 打卡任务ID                                                   |          |
+| status_date                      | date        | 记录状态的时间                                               |          |
+| task_continue_status             | varchar(20) | 任务连续打卡状态(连续打卡-CONTINUE、中断-INTERRUPTED)        |          |
+| task_continue_day                | int         | 任务连续天数,第一天开始就等于1                              |          |
+| continue_stage                   | varchar(10) | 连续阶段(宽限期-GRACE_STAGE,正常打卡期-NORMAL_STAGE,惩罚期-PENALTY_STAGE) |          |
+| stage_start_date                 | date        | 阶段开始日期                                                 |          |
+| stage_end_date                   | date        | 阶段结束日期                                                 |          |
+| continue_interrupted_count       | int         | 连续中断次数                                                 |          |
+| repeat_category                  | varchar(10) | 重复周期类型(每日-EVERYDAY、法定工作日-WORKDAY、法定节假日(含周末)-HOLIDAY、自定义(周一至周日)-CUSTOM) |          |
+| repeat_custom_day                | varchar(13) | 自定义重复日(周一-1,周二-2,周三-3,周四-4,周五-5,周六-6,周日-7) |          |
+| repeat_start_date_in_week        | date        | 本周重复周期开始时间                                         |          |
+| repeat_prev_total_count_in_week  | int         | 本周需打卡数(变更重复类型前)                               |          |
+| repeat_start_date_in_month       | date        | 本月重复周期开始时间                                         |          |
+| repeat_prev_total_count_in_month | int         | 本月需打卡数(变更重复类型前)                               |          |
+| stat_time_in_week                | char(8)     | 本周时间(格式:yyyy-W周数)                                 |          |
+| punch_in_total_count_in_week     | int         | 本周需打卡数                                                 |          |
+| punch_in_count_in_week           | int         | 本周已打卡数                                                 |          |
+| punch_in_done_count_in_week      | int         | 本周完成打卡数                                               |          |
+| points_in_week                   | int         | 本周获取积分数                                               |          |
+| stat_time_in_month               | char(7)     | 本月时间(格式:yyyy-MM)                                    |          |
+| punch_in_total_count_in_month    | int         | 本月需打卡数                                                 |          |
+| punch_in_count_in_month          | int         | 本月已打卡数                                                 |          |
+| punch_in_done_count_in_month     | int         | 本月完成打卡数                                               |          |
+| points_in_month                  | int         | 本月获取积分数                                               |          |
+| created_by                       | bigint      | 创建人                                                       |          |
+| creation_time                    | timestamp   | 创建时间                                                     |          |
+| last_updated_by                  | bigint      | 最后更新人                                                   |          |
+| last_update_time                 | timestamp   | 最后更新时间                                                 |          |
+| version                          | bigint      | 版本号                                                       |          |
+| delete_flag                      | tinyint     | 逻辑删除标志(0-未删除,1-已删除)                           |          |
 
 
 
@@ -837,39 +850,43 @@ ui设计工具:即时设计
 
 作用:multi_task_unique_id和task_unique_id字段不能同时出现,是一张公用表,multi_task_unique_id出现时是多任务的打卡状态,task_unique_id出现时是单任务的打卡状态
 
-| 字段                          | 类型        | 描述                                                         | 索引     |
-| ----------------------------- | ----------- | ------------------------------------------------------------ | -------- |
-| id                            | bigint      | 主键                                                         | 主键索引 |
-| user_id                       | bigint      | 用户ID                                                       | 普通索引 |
-| multi_task_unique_id          | bigint      | 打卡多任务唯一ID                                             | 普通索引 |
-| multi_task_id                 | bigint      | 打卡多任务ID                                                 |          |
-| task_unique_id                | bigint      | 打卡任务唯一ID                                               | 普通索引 |
-| taks_id                       | bigint      | 打卡任务ID                                                   |          |
-| status_date                   | date        | 记录状态的时间                                               | 普通索引 |
-| task_continue_status          | varchar(20) | 任务连续打卡状态(连续打卡-CONTINUE、中断-INTERRUPTED)        |          |
-| task_continue_day             | int         | 任务连续天数,第一天开始就等于1                              |          |
-| continue_stage                | varchar(10) | 连续阶段(宽限期-GRACE_STAGE,正常打卡期-NORMAL_STAGE,惩罚期-PENALTY_STAGE) |          |
-| stage_start_date              | date        | 阶段开始日期                                                 |          |
-| stage_end_date                | date        | 阶段结束日期                                                 |          |
-| continue_interrupted_count    | int         | 连续中断次数                                                 |          |
-| stat_time_in_week             | char(8)     | 本周时间(格式:yyyy-W周数)                                 |          |
-| punch_in_total_count_in_week  | int         | 本周需打卡数                                                 |          |
-| punch_in_count_in_week        | int         | 本周已打卡数                                                 |          |
-| punch_in_done_count_in_week   | int         | 本周完成打卡数                                               |          |
-| points_in_week                | int         | 本周获取积分数                                               |          |
-| stat_time_in_month            | char(7)     | 本月时间(格式:yyyy-MM)                                    |          |
-| punch_in_total_count_in_month | int         | 本月需打卡数                                                 |          |
-| punch_in_count_in_month       | int         | 本月已打卡数                                                 |          |
-| punch_in_done_count_in_month  | int         | 本月完成打卡数                                               |          |
-| points_in_month               | int         | 本月获取积分数                                               |          |
-| created_by                    | bigint      | 创建人                                                       |          |
-| creation_time                 | timestamp   | 创建时间                                                     |          |
-| last_updated_by               | bigint      | 最后更新人                                                   |          |
-| last_update_time              | timestamp   | 最后更新时间                                                 |          |
-| version                       | bigint      | 版本号                                                       |          |
-| delete_flag                   | tinyint     | 逻辑删除标志(0-未删除,1-已删除)                           |          |
-
-
+| 字段                             | 类型        | 描述                                                         | 索引     |
+| -------------------------------- | ----------- | ------------------------------------------------------------ | -------- |
+| id                               | bigint      | 主键                                                         | 主键索引 |
+| user_id                          | bigint      | 用户ID                                                       | 普通索引 |
+| multi_task_unique_id             | bigint      | 打卡多任务唯一ID                                             | 普通索引 |
+| multi_task_id                    | bigint      | 打卡多任务ID                                                 |          |
+| task_unique_id                   | bigint      | 打卡任务唯一ID                                               | 普通索引 |
+| taks_id                          | bigint      | 打卡任务ID                                                   |          |
+| status_date                      | date        | 记录状态的时间                                               |          |
+| task_continue_status             | varchar(20) | 任务连续打卡状态(连续打卡-CONTINUE、中断-INTERRUPTED)        |          |
+| task_continue_day                | int         | 任务连续天数,第一天开始就等于1                              |          |
+| continue_stage                   | varchar(10) | 连续阶段(宽限期-GRACE_STAGE,正常打卡期-NORMAL_STAGE,惩罚期-PENALTY_STAGE) |          |
+| stage_start_date                 | date        | 阶段开始日期                                                 |          |
+| stage_end_date                   | date        | 阶段结束日期                                                 |          |
+| continue_interrupted_count       | int         | 连续中断次数                                                 |          |
+| repeat_category                  | varchar(10) | 重复周期类型(每日-EVERYDAY、法定工作日-WORKDAY、法定节假日(含周末)-HOLIDAY、自定义(周一至周日)-CUSTOM) |          |
+| repeat_custom_day                | varchar(13) | 自定义重复日(周一-1,周二-2,周三-3,周四-4,周五-5,周六-6,周日-7) |          |
+| repeat_start_date_in_week        | date        | 本周重复周期开始时间                                         |          |
+| repeat_prev_total_count_in_week  | int         | 本周需打卡数(变更重复类型前)                               |          |
+| repeat_start_date_in_month       | date        | 本月重复周期开始时间                                         |          |
+| repeat_prev_total_count_in_month | int         | 本月需打卡数(变更重复类型前)                               |          |
+| stat_time_in_week                | char(8)     | 本周时间(格式:yyyy-W周数)                                 |          |
+| punch_in_total_count_in_week     | int         | 本周需打卡数                                                 |          |
+| punch_in_count_in_week           | int         | 本周已打卡数                                                 |          |
+| punch_in_done_count_in_week      | int         | 本周完成打卡数                                               |          |
+| points_in_week                   | int         | 本周获取积分数                                               |          |
+| stat_time_in_month               | char(7)     | 本月时间(格式:yyyy-MM)                                    |          |
+| punch_in_total_count_in_month    | int         | 本月需打卡数                                                 |          |
+| punch_in_count_in_month          | int         | 本月已打卡数                                                 |          |
+| punch_in_done_count_in_month     | int         | 本月完成打卡数                                               |          |
+| points_in_month                  | int         | 本月获取积分数                                               |          |
+| created_by                       | bigint      | 创建人                                                       |          |
+| creation_time                    | timestamp   | 创建时间                                                     |          |
+| last_updated_by                  | bigint      | 最后更新人                                                   |          |
+| last_update_time                 | timestamp   | 最后更新时间                                                 |          |
+| version                          | bigint      | 版本号                                                       |          |
+| delete_flag                      | tinyint     | 逻辑删除标志(0-未删除,1-已删除)                           |          |
 
 
 

+ 3 - 1
src/main/java/com/punchsettle/server/atomic/entity/PiMultiTaskHistory.java

@@ -7,6 +7,7 @@ import java.time.LocalDate;
 import com.punchsettle.server.common.pojo.BaseEntity;
 
 import com.punchsettle.server.constant.PunchInResultEnum;
+import com.punchsettle.server.constant.SettleResultEnum;
 import jakarta.persistence.Column;
 import jakarta.persistence.Table;
 import lombok.Data;
@@ -102,9 +103,10 @@ public class PiMultiTaskHistory extends BaseEntity implements Serializable {
 
     /**
      * 结算结果(未结算-UNSETTLED,已结算-SETTLED)
+     * @see SettleResultEnum
      */
     @Column(name = "settle_result")
-    private String settleResult;
+    private SettleResultEnum settleResult;
 
     /**
      * 结算任务执行ID

+ 38 - 0
src/main/java/com/punchsettle/server/atomic/entity/PiStatus.java

@@ -8,6 +8,7 @@ import java.time.LocalDate;
 import com.punchsettle.server.common.pojo.BaseEntity;
 import com.punchsettle.server.constant.ContinueStageEnum;
 import com.punchsettle.server.constant.ContinueStatusEnum;
+import com.punchsettle.server.constant.RepeatCategoryEnum;
 import jakarta.persistence.Column;
 import jakarta.persistence.Table;
 import lombok.Data;
@@ -89,6 +90,43 @@ public class PiStatus extends BaseEntity implements Serializable {
     @Column(name = "连续中断次数")
     private Integer continueInterruptedCount;
 
+    /**
+     * 重复周期类型(每日-EVERYDAY、法定工作日-WORKDAY、法定节假日(含周末)-HOLIDAY、自定义(周一至周日)-CUSTOM)
+     * @see RepeatCategoryEnum
+     */
+    @Column(name = "repeat_category")
+    private RepeatCategoryEnum repeatCategory;
+
+    /**
+     * 自定义重复日(周一-1,周二-2,周三-3,周四-4,周五-5,周六-6,周日-7)
+     */
+    @Column(name = "repeat_custom_day")
+    private String repeatCustomDay;
+
+    /**
+     * 本周重复周期开始时间
+     */
+    @Column(name = "repeat_start_date_in_week")
+    private LocalDate repeatStartDateInWeek;
+
+    /**
+     * 本周需打卡数(变更重复类型前)
+     */
+    @Column(name = "repeat_prev_total_count_in_week")
+    private Integer repeatPrevTotalCountInWeek;
+
+    /**
+     * 本月重复周期开始时间
+     */
+    @Column(name = "repeat_start_date_in_month")
+    private LocalDate repeatStartDateInMonth;
+
+    /**
+     * 本月需打卡数(变更重复类型前)
+     */
+    @Column(name = "repeat_prev_total_count_in_month")
+    private Integer repeatPrevTotalCountInMonth;
+
     /**
      * 统计时间(格式:yyyy-W周数)
      */

+ 44 - 0
src/main/java/com/punchsettle/server/atomic/entity/PiStatusHistory.java

@@ -7,6 +7,7 @@ import java.time.LocalDate;
 
 import com.punchsettle.server.common.pojo.BaseEntity;
 import com.punchsettle.server.constant.ContinueStatusEnum;
+import com.punchsettle.server.constant.RepeatCategoryEnum;
 import jakarta.persistence.Column;
 import jakarta.persistence.Table;
 import lombok.Data;
@@ -87,6 +88,49 @@ public class PiStatusHistory extends BaseEntity implements Serializable {
     @Column(name = "连续中断次数")
     private Integer continueInterruptedCount;
 
+    /**
+     * 重复周期类型(每日-EVERYDAY、法定工作日-WORKDAY、法定节假日(含周末)-HOLIDAY、自定义(周一至周日)-CUSTOM)
+     * @see RepeatCategoryEnum
+     */
+    @Column(name = "repeat_category")
+    private RepeatCategoryEnum repeatCategory;
+
+    /**
+     * 自定义重复日(周一-1,周二-2,周三-3,周四-4,周五-5,周六-6,周日-7)
+     */
+    @Column(name = "repeat_custom_day")
+    private String repeatCustomDay;
+
+    /**
+     * 重复周期开始时间
+     */
+    @Column(name = "repeat_start_date")
+    private LocalDate repeatStartDate;
+
+    /**
+     * 本周重复周期开始时间
+     */
+    @Column(name = "repeat_start_date_in_week")
+    private LocalDate repeatStartDateInWeek;
+
+    /**
+     * 本周需打卡数(变更重复类型前)
+     */
+    @Column(name = "repeat_prev_total_count_in_week")
+    private Integer repeatPrevTotalCountInWeek;
+
+    /**
+     * 本月重复周期开始时间
+     */
+    @Column(name = "repeat_start_date_in_month")
+    private LocalDate repeatStartDateInMonth;
+
+    /**
+     * 本月需打卡数(变更重复类型前)
+     */
+    @Column(name = "repeat_prev_total_count_in_month")
+    private Integer repeatPrevTotalCountInMonth;
+
     /**
      * 统计时间(格式:yyyy-W周数)
      */

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

@@ -120,10 +120,10 @@ public class PiTaskHistory extends BaseEntity implements Serializable {
     private Long settleTaskHistoryId;
 
     /**
-     * 结算时的打卡任务ID
+     * 结算时的打卡任务ID
      */
-    @Column(name = "settle_pi_multi_task_id")
-    private Long settlePiMultiTaskId;
+    @Column(name = "settle_pi_task_id")
+    private Long settlePiTaskId;
 
     /**
      * 结算奖励积分

+ 2 - 1
src/main/java/com/punchsettle/server/atomic/mapper/PiStatusHistoryMapper.java

@@ -2,6 +2,7 @@ package com.punchsettle.server.atomic.mapper;
 
 import com.punchsettle.server.atomic.entity.PiStatusHistory;
 import tk.mybatis.mapper.common.Mapper;
+import tk.mybatis.mapper.common.special.InsertListMapper;
 
 /**
  * @author tyuio
@@ -9,6 +10,6 @@ import tk.mybatis.mapper.common.Mapper;
  * @description 打卡任务状态记录表 Mapper
  * @date 2025/04/08 10:30
  */
-public interface PiStatusHistoryMapper extends Mapper<PiStatusHistory> {
+public interface PiStatusHistoryMapper extends Mapper<PiStatusHistory>, InsertListMapper<PiStatusHistory> {
 
 }

+ 2 - 1
src/main/java/com/punchsettle/server/atomic/mapper/PiStatusMapper.java

@@ -1,6 +1,7 @@
 package com.punchsettle.server.atomic.mapper;
 
 import com.punchsettle.server.atomic.entity.PiStatus;
+import tk.mybatis.mapper.additional.update.batch.BatchUpdateSelectiveMapper;
 import tk.mybatis.mapper.common.Mapper;
 
 /**
@@ -9,6 +10,6 @@ import tk.mybatis.mapper.common.Mapper;
  * @description 打卡任务状态表 Mapper
  * @date 2025/04/08 10:30
  */
-public interface PiStatusMapper extends Mapper<PiStatus> {
+public interface PiStatusMapper extends Mapper<PiStatus>, BatchUpdateSelectiveMapper<PiStatus> {
 
 }

+ 2 - 1
src/main/java/com/punchsettle/server/atomic/mapper/StatPiTaskMonthMapper.java

@@ -2,6 +2,7 @@ package com.punchsettle.server.atomic.mapper;
 
 import com.punchsettle.server.atomic.entity.StatPiTaskMonth;
 import tk.mybatis.mapper.common.Mapper;
+import tk.mybatis.mapper.common.special.InsertListMapper;
 
 /**
  * @author tyuio
@@ -9,6 +10,6 @@ import tk.mybatis.mapper.common.Mapper;
  * @description 打卡任务月数据统计 Mapper
  * @date 2025/04/08 10:30
  */
-public interface StatPiTaskMonthMapper extends Mapper<StatPiTaskMonth> {
+public interface StatPiTaskMonthMapper extends Mapper<StatPiTaskMonth>, InsertListMapper<StatPiTaskMonth> {
 
 }

+ 2 - 1
src/main/java/com/punchsettle/server/atomic/mapper/StatPiTaskWeekMapper.java

@@ -3,6 +3,7 @@ package com.punchsettle.server.atomic.mapper;
 import com.punchsettle.server.atomic.entity.StatPiTaskWeek;
 
 import tk.mybatis.mapper.common.Mapper;
+import tk.mybatis.mapper.common.special.InsertListMapper;
 
 /**
  * @author tyuio
@@ -10,6 +11,6 @@ import tk.mybatis.mapper.common.Mapper;
  * @description 打卡任务周数据统计 Mapper
  * @date 2025/04/08 10:30
  */
-public interface StatPiTaskWeekMapper extends Mapper<StatPiTaskWeek> {
+public interface StatPiTaskWeekMapper extends Mapper<StatPiTaskWeek>, InsertListMapper<StatPiTaskWeek> {
 
 }

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

@@ -1,5 +1,9 @@
 package com.punchsettle.server.atomic.service;
 
+import com.punchsettle.server.atomic.entity.PiStatusHistory;
+
+import java.util.List;
+
 /**
  * @author tyuio
  * @version 1.0.0
@@ -7,4 +11,10 @@ package com.punchsettle.server.atomic.service;
  * @description 打卡任务状态记录表 service
  */
 public interface IPiStatusHistoryService {
+
+    /**
+     * 批量新增
+     * @param piStatusHistories
+     */
+    void insertList(List<PiStatusHistory> piStatusHistories);
 }

+ 6 - 0
src/main/java/com/punchsettle/server/atomic/service/IPiStatusService.java

@@ -19,4 +19,10 @@ public interface IPiStatusService {
      * @return
      */
     List<PiStatus> queryByCondition(PiStatusQuery piStatusQuery);
+
+    /**
+     * 批量更新
+     * @param piStatusList
+     */
+    void batchUpdate(List<PiStatus> piStatusList);
 }

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

@@ -19,4 +19,10 @@ public interface IStatPiTaskMonthService {
      * @return
      */
     List<StatPiTaskMonth> queryByCondition(PiStatsMonthQuery piStatsMonthQuery);
+
+    /**
+     * 批量新增
+     * @param statPiTaskMonthList
+     */
+    void insertList(List<StatPiTaskMonth> statPiTaskMonthList);
 }

+ 6 - 0
src/main/java/com/punchsettle/server/atomic/service/IStatPiTaskWeekService.java

@@ -19,4 +19,10 @@ public interface IStatPiTaskWeekService {
      * @return
      */
     List<StatPiTaskWeek> queryByCondition(StatPiTaskWeekQuery statPiTaskWeekQuery);
+
+    /**
+     * 批量新增
+     * @param statPiTaskWeekList
+     */
+    void insertList(List<StatPiTaskWeek> statPiTaskWeekList);
 }

+ 1 - 1
src/main/java/com/punchsettle/server/atomic/service/impl/PiMultiTaskRelaServiceImpl.java

@@ -33,7 +33,7 @@ public class PiMultiTaskRelaServiceImpl implements IPiMultiTaskRelaService {
         Weekend<PiMultiTaskRela> weekend = WeekendUtils.createExcludeAuditFields(PiMultiTaskRela.class);
         WeekendCriteria<PiMultiTaskRela, Object> criteria = weekend.weekendCriteria();
         if (!CollectionUtils.isEmpty(multiTaskIds)) {
-            criteria.andIn(PiMultiTaskRela::getPunchInMultiTaskId, multiTaskIds);
+            criteria.andIn(PiMultiTaskRela::getMultiTaskId, multiTaskIds);
         }
         return piMultiTaskRelaMapper.selectByExample(weekend);
     }

+ 15 - 0
src/main/java/com/punchsettle/server/atomic/service/impl/PiStatusHistoryServiceImpl.java

@@ -1,8 +1,14 @@
 package com.punchsettle.server.atomic.service.impl;
 
+import com.punchsettle.server.atomic.entity.PiStatusHistory;
+import com.punchsettle.server.atomic.mapper.PiStatusHistoryMapper;
 import com.punchsettle.server.atomic.service.IPiStatusHistoryService;
+import com.punchsettle.server.common.utils.Assert;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
+import java.util.List;
+
 /**
  * @author tyuio
  * @version 1.0.0
@@ -11,4 +17,13 @@ import org.springframework.stereotype.Service;
  */
 @Service
 public class PiStatusHistoryServiceImpl implements IPiStatusHistoryService {
+
+    @Autowired
+    private PiStatusHistoryMapper piStatusHistoryMapper;
+
+    @Override
+    public void insertList(List<PiStatusHistory> piStatusHistories) {
+        Assert.notEmpty(piStatusHistories);
+        piStatusHistoryMapper.insertList(piStatusHistories);
+    }
 }

+ 7 - 1
src/main/java/com/punchsettle/server/atomic/service/impl/PiStatusServiceImpl.java

@@ -33,11 +33,17 @@ public class PiStatusServiceImpl implements IPiStatusService {
         Weekend<PiStatus> weekend = WeekendUtils.createExcludeAuditFields(PiStatus.class);
         WeekendCriteria<PiStatus, Object> criteria = weekend.weekendCriteria();
         if (!CollectionUtils.isEmpty(piStatusQuery.getTaskUniqueIds())) {
-            criteria.andIn(PiStatus::getPunchInTaskUniqueId, piStatusQuery.getTaskUniqueIds());
+            criteria.andIn(PiStatus::getTaskUniqueId, piStatusQuery.getTaskUniqueIds());
         }
         if (!CollectionUtils.isEmpty(piStatusQuery.getUserIds())) {
             criteria.andIn(PiStatus::getUserId, piStatusQuery.getUserIds());
         }
         return piStatusMapper.selectByExample(weekend);
     }
+
+    @Override
+    public void batchUpdate(List<PiStatus> piStatusList) {
+        Assert.notEmpty(piStatusList);
+        piStatusMapper.batchUpdateSelective(piStatusList);
+    }
 }

+ 1 - 1
src/main/java/com/punchsettle/server/atomic/service/impl/PiTaskExtServiceImpl.java

@@ -33,7 +33,7 @@ public class PiTaskExtServiceImpl implements IPiTaskExtService {
         Weekend<PiTaskExt> weekend = WeekendUtils.createExcludeAuditFields(PiTaskExt.class);
         WeekendCriteria<PiTaskExt, Object> criteria = weekend.weekendCriteria();
         if (!CollectionUtils.isEmpty(piTaskExtQuery.getPunchInTaskIds())) {
-            criteria.andIn(PiTaskExt::getPunchInTaskId, piTaskExtQuery.getPunchInTaskIds());
+            criteria.andIn(PiTaskExt::getTaskId, piTaskExtQuery.getPunchInTaskIds());
         }
         return piTaskExtMapper.selectByExample(weekend);
     }

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

@@ -39,6 +39,9 @@ public class PiTaskServiceImpl implements IPiTaskService {
         if (Objects.nonNull(piTaskQuery.getTaskStatus())) {
             criteria.andEqualTo(PiTask::getTaskStatus, piTaskQuery.getTaskStatus());
         }
+        if (Objects.nonNull(piTaskQuery.getArchiveStatus())) {
+            criteria.andEqualTo(PiTask::getArchiveStatus, piTaskQuery.getArchiveStatus());
+        }
         return piTaskMapper.selectByExample(weekend);
     }
 }

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

@@ -41,4 +41,10 @@ public class StatPiTaskMonthServiceImpl implements IStatPiTaskMonthService {
         }
         return statPiTaskMonthMapper.selectByExample(weekend);
     }
+
+    @Override
+    public void insertList(List<StatPiTaskMonth> statPiTaskMonthList) {
+        Assert.notEmpty(statPiTaskMonthList);
+        statPiTaskMonthMapper.insertList(statPiTaskMonthList);
+    }
 }

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

@@ -24,4 +24,10 @@ public class PiTaskQuery {
      * @see ArchiveStatusEnum
      */
     private ArchiveStatusEnum taskStatus;
+
+    /**
+     * 归档状态(活跃-ACTIVE,归档-ARCHIVE)
+     * @see ArchiveStatusEnum
+     */
+    private ArchiveStatusEnum archiveStatus;
 }

+ 7 - 12
src/main/java/com/punchsettle/server/service/manager/IPunchInManager.java

@@ -6,6 +6,7 @@ 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;
@@ -43,20 +44,14 @@ public interface IPunchInManager {
     PunchInResultEnum judgePunchInResultInMultiTask(PiMultiTask piMultiTask, List<PiTaskHistory> piTaskHistoryList);
 
     /**
-     * 根据打卡任务获取指定日期所在周需打卡总次数
-     * @param piTask 打卡任务
-     * @param specifiedDateStr 指定日期
-     * @return
-     */
-    int getPunchInTotalCountInWeek(PiTask piTask, String specifiedDateStr);
-
-    /**
-     * 根据打卡任务获取指定日期所在月需打卡总次数
-     * @param piTask 打卡任务
-     * @param specifiedDateStr 指定日期
+     * 根据重复类型计算指定日期范围内的总打卡次数
+     * @param repeatCategory 重复类型
+     * @param repeatCustomDay 自定义重复日(周一-1,周二-2,周三-3,周四-4,周五-5,周六-6,周日-7
+     * @param repeatStartDate 重复开始日期
+     * @param repeatEndDate 重复结束日期
      * @return
      */
-    int getPunchInTotalCountInMonth(PiTask piTask, String specifiedDateStr);
+    int getPunchInTotalCountInRange(RepeatCategoryEnum repeatCategory, String repeatCustomDay, LocalDate repeatStartDate, LocalDate repeatEndDate);
 
     /**
      * 判断打卡任务在指定日期的连续打卡阶段

+ 9 - 45
src/main/java/com/punchsettle/server/service/manager/impl/PunchInManagerImpl.java

@@ -2,6 +2,7 @@ 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;
@@ -141,63 +142,26 @@ public class PunchInManagerImpl implements IPunchInManager {
     }
 
     @Override
-    public int getPunchInTotalCountInWeek(PiTask piTask, String specifiedDateStr) {
-        Assert.isNullInBusiness(piTask, "打卡任务不能为空 ");
-        Assert.isNull(specifiedDateStr, "指定日期不能为空 ");
-
-        if (RepeatCategoryEnum.EVERYDAY.equals(piTask.getRepeatCategory())) {
-            return 7;
-        }
+    public int getPunchInTotalCountInRange(RepeatCategoryEnum repeatCategory, String repeatCustomDay, LocalDate repeatStartDate, LocalDate repeatEndDate) {
 
-        if (RepeatCategoryEnum.CUSTOM.equals(piTask.getRepeatCategory())) {
-            return piTask.getRepeatCustomDay().split(",").length;
+        if (RepeatCategoryEnum.EVERYDAY.equals(repeatCategory)) {
+            return (int) ChronoUnit.DAYS.between(repeatStartDate, repeatEndDate.plusDays(1));
         }
 
-        // 指定日期
-        LocalDate specifiedDate = LocalDate.parse(specifiedDateStr);
-
-        if (RepeatCategoryEnum.WORKDAY.equals(piTask.getRepeatCategory())) {
-            List<LocalDate> dateRange = DateUtils.getDateRangeInWeek(specifiedDate);
-            return (int) dateRange.stream().map(v -> DateUtils.YYYY_MM_DD_FORMATTER.format(v))
-                    .filter(v -> calendarManager.judgeWorkday(v)).count();
-        }
-
-        if (RepeatCategoryEnum.HOLIDAY.equals(piTask.getRepeatCategory())) {
-            List<LocalDate> dateRange = DateUtils.getDateRangeInWeek(specifiedDate);
-            return (int) dateRange.stream().map(v -> DateUtils.YYYY_MM_DD_FORMATTER.format(v))
-                    .filter(v -> calendarManager.judgeHoliday(v)).count();
-        }
+        List<LocalDate> dateRange = DateUtils.getDateRange(repeatStartDate, repeatEndDate);
 
-        return 0;
-    }
-
-    @Override
-    public int getPunchInTotalCountInMonth(PiTask piTask, String specifiedDateStr) {
-        Assert.isNullInBusiness(piTask, "打卡任务不能为空 ");
-        Assert.isNull(specifiedDateStr, "指定日期不能为空 ");
-
-        // 指定日期
-        LocalDate specifiedDate = LocalDate.parse(specifiedDateStr);
-
-        if (RepeatCategoryEnum.EVERYDAY.equals(piTask.getRepeatCategory())) {
-            return specifiedDate.lengthOfMonth();
-        }
-
-        // 日期列表
-        List<LocalDate> dateRange = DateUtils.getDateRangeInMonth(specifiedDate);
-
-        if (RepeatCategoryEnum.CUSTOM.equals(piTask.getRepeatCategory())) {
-            String[] split = piTask.getRepeatCustomDay().split(",");
+        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(piTask.getRepeatCategory())) {
+        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(piTask.getRepeatCategory())) {
+        if (RepeatCategoryEnum.HOLIDAY.equals(repeatCategory)) {
             return (int) dateRange.stream().map(v -> DateUtils.YYYY_MM_DD_FORMATTER.format(v))
                     .filter(v -> calendarManager.judgeHoliday(v)).count();
         }

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

@@ -544,7 +544,7 @@ public class PunchInManagerV1Impl implements IPunchInManagerV1 {
         }
 
         // 完成的打卡数量
-        long punchInDoneCount = piTaskHistoryList.stream().filter(v -> PunchInResultEnum.DONE.equals(v.getPunchInStatus())).count();
+        long punchInDoneCount = piTaskHistoryList.stream().filter(v -> PunchInResultEnum.DONE.equals(v.getPunchInResult())).count();
 
 //        // 次数,当天打卡次数大于等于设置的次数,则完成打卡
 //        if (PunchInMethodMultiEnum.COUNT.equals(punchInMultiTask.getPunchInMethod())) {
@@ -568,7 +568,7 @@ public class PunchInManagerV1Impl implements IPunchInManagerV1 {
     @Override
     public int calculatePointsInTask(PiTask piTask, List<PiTaskExt> piTaskExts, PiTaskHistory piTaskHistory, StatPiTaskWeek statPiTaskWeek, StatPiTaskMonth statPiTaskMonth, PiStatus piStatus) {
         // 未完成打卡,积分为0
-        if (PunchInResultEnum.UNDONE.equals(piTaskHistory.getPunchInStatus())) {
+        if (PunchInResultEnum.UNDONE.equals(piTaskHistory.getPunchInResult())) {
             return 0;
         }
 
@@ -710,7 +710,7 @@ public class PunchInManagerV1Impl implements IPunchInManagerV1 {
     @Override
     public int calculatePointsInMultiTask(PiMultiTask piMultiTask, List<PiMultiTaskExt> piMultiTaskExts, PiMultiTaskHistory piMultiTaskHistory, PiStatus piStatus) {
         // 未完成打卡或没有启用多任务积分计算,积分为0
-        if (PunchInResultEnum.UNDONE.equals(piMultiTaskHistory.getPunchInStatus())
+        if (PunchInResultEnum.UNDONE.equals(piMultiTaskHistory.getPunchInResult())
             || CommonEnableStatusEnum.ENABLED.equals(piMultiTask.getTaskPointsStatus())) {
             return 0;
         }

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

@@ -268,7 +268,7 @@ public class SettleManagerImpl implements ISettleManager {
                                           List<PiMultiTaskExt> piMultiTaskExtList, PiMultiTaskHistory piMultiTaskHistory,
                                           PiStatus piStatus) {
         // 未完成打卡或没有启用多任务积分计算,积分为0
-        if (PunchInResultEnum.UNDONE.equals(piMultiTaskHistory.getPunchInStatus())
+        if (PunchInResultEnum.UNDONE.equals(piMultiTaskHistory.getPunchInResult())
             || CommonEnableStatusEnum.DISABLED.equals(piMultiTask.getTaskPointsStatus())) {
             return 0;
         }

+ 6 - 0
src/main/java/com/punchsettle/server/service/manager/impl/StatPiTaskWeekServiceImpl.java

@@ -43,4 +43,10 @@ public class StatPiTaskWeekServiceImpl implements IStatPiTaskWeekService {
         }
         return statPiTaskWeekMapper.selectByExample(weekend);
     }
+
+    @Override
+    public void insertList(List<StatPiTaskWeek> statPiTaskWeekList) {
+        Assert.notEmpty(statPiTaskWeekList);
+        statPiTaskWeekMapper.insertList(statPiTaskWeekList);
+    }
 }

+ 243 - 59
src/main/java/com/punchsettle/server/task/PunchInCoreTask.java

@@ -5,13 +5,17 @@ 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.StatPiTaskMonth;
+import com.punchsettle.server.atomic.entity.StatPiTaskWeek;
 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.IStatPiTaskMonthService;
 import com.punchsettle.server.atomic.service.IStatPiTaskWeekService;
 import com.punchsettle.server.atomic.service.IPiStatusService;
@@ -37,10 +41,13 @@ 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 javax.swing.text.html.Option;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.time.DayOfWeek;
 import java.time.LocalDate;
 import java.util.ArrayList;
@@ -99,35 +106,48 @@ public class PunchInCoreTask {
     //
     // }
 
+    /**
+     * 默认数值100
+     */
+    private static final BigDecimal ONE_HUNDRED = new BigDecimal(100);
+
+    /**
+     * 默认百分比 0.00%
+     */
+    private static final BigDecimal ZERO_RATE = new BigDecimal("0.00");
+
+    @Autowired
+    private IPiTaskService piTaskService;
+
     @Autowired
-    private IPiTaskService punchInTaskService;
+    private IPiTaskExtService piTaskExtService;
 
     @Autowired
-    private IPiTaskExtService punchInTaskExtService;
+    private IPiTaskHistoryService piTaskHistoryService;
 
     @Autowired
-    private IPiTaskHistoryService punchInTaskHistoryService;
+    private IStatPiTaskMonthService statPiTaskMonthService;
 
     @Autowired
-    private IStatPiTaskMonthService punchInStatsMonthService;
+    private IStatPiTaskWeekService statPiTaskWeekService;
 
     @Autowired
-    private IStatPiTaskWeekService punchInStatsWeekService;
+    private IPiStatusService piStatusService;
 
     @Autowired
-    private IPiStatusService punchInStatusService;
+    private IPiStatusHistoryService piStatusHistoryService;
 
     @Autowired
-    private IPiMultiTaskService punchInMultiTaskService;
+    private IPiMultiTaskService piMultiTaskService;
 
     @Autowired
-    private IPiMultiTaskExtService punchInMultiTaskExtService;
+    private IPiMultiTaskExtService piMultiTaskExtService;
 
     @Autowired
-    private IPiMultiTaskHistoryService punchInMultiTaskHistoryService;
+    private IPiMultiTaskHistoryService piMultiTaskHistoryService;
 
     @Autowired
-    private IPiMultiTaskRelaService punchInMultiTaskRelaService;
+    private IPiMultiTaskRelaService piMultiTaskRelaService;
 
     @Autowired
     private ICalendarManager calendarManager;
@@ -145,8 +165,16 @@ public class PunchInCoreTask {
         boolean isFirstDayOfMonth = punchInDate.getDayOfMonth() == 1;
         // 是否打卡所在月最后一天
         boolean isLastDayOfMonth = punchInDate.getDayOfMonth() == punchInDate.lengthOfMonth();
-
-        List<PiTaskHistory> updatePunchInTaskHistories = new ArrayList<>(punchInSettleData.size());
+        // 周期数
+        String yearWeek = DateUtils.getYearWeek(punchInDate);
+        // 月份数
+        String yearMonth = DateUtils.getYearMonth(punchInDate);
+
+        List<PiStatusHistory> addPiStatusHistories = new ArrayList<>();
+        List<StatPiTaskWeek> addStatPiTaskWeekList = new ArrayList<>();
+        List<StatPiTaskMonth> addStatPiTaskMonthList = new ArrayList<>();
+        List<PiStatus> updatePiStatusList = new ArrayList<>();
+        List<PiTaskHistory> updatePunchInTaskHistories = new ArrayList<>();
         List<PiMultiTaskHistory> updatePunchInMultiTaskHistories = new ArrayList<>(punchInSettleData.size());
         for (PunchInSettleData punchInSettle : punchInSettleData) {
             // 单任务处理部分
@@ -156,6 +184,10 @@ public class PunchInCoreTask {
                 PiStatus piStatus = piTaskData.getPiStatus();
                 List<PiTaskExt> piTaskExtList = piTaskData.getPiTaskExtList();
 
+                // 变更前记录历史状态
+                PiStatusHistory piStatusHistory = new PiStatusHistory();
+                BeanUtils.copyProperties(piStatus, piStatusHistory);
+
                 PiTaskHistory updatePiTaskHistory = new PiTaskHistory();
                 updatePiTaskHistory.setId(piTaskHistory.getId());
 
@@ -177,55 +209,102 @@ public class PunchInCoreTask {
 
                 // 设置任务连续状态
                 ContinueStatusEnum oldTaskContinueStatus = piStatus.getTaskContinueStatus();
-                piStatus.setTaskContinueStatus(punchInResult.equals(PunchInResultEnum.DONE) ? ContinueStatusEnum.CONTINUE : ContinueStatusEnum.INTERRUPTED);
-                piStatus.setTaskContinueDay(oldTaskContinueStatus.equals(piStatus.getTaskContinueStatus()) ? piStatus.getTaskContinueDay() + 1 : 1);
+                piStatus.setTaskContinueStatus(punchInResult.equals(PunchInResultEnum.DONE)
+                    ? ContinueStatusEnum.CONTINUE : ContinueStatusEnum.INTERRUPTED);
+                piStatus.setTaskContinueDay(oldTaskContinueStatus.equals(piStatus.getTaskContinueStatus())
+                    ? piStatus.getTaskContinueDay() + 1 : 1);
 
                 // 旧的连续阶段
                 ContinueStageEnum oldContinueStage = piStatus.getContinueStage();
                 // 判断当前处于的连续阶段
-                ContinueStageEnum continueStageResult = punchInManager.judgeContinueStageInTask(piTask, piTaskHistory, piStatus, punchInDate);
+                ContinueStageEnum continueStageResult =
+                    punchInManager.judgeContinueStageInTask(piTask, piTaskHistory, piStatus, punchInDate);
                 piStatus.setContinueStage(continueStageResult);
                 // 下面3种情况不处理:宽限期 变 宽限期;正常打卡期 变 正常打卡期;惩罚期 变 惩罚期;
                 // 宽限期 变 正常打卡期,则设置阶段开始时间,重置中断次数
-                if (ContinueStageEnum.GRACE_STAGE.equals(oldContinueStage) && ContinueStageEnum.NORMAL_STAGE.equals(continueStageResult)) {
+                if (ContinueStageEnum.GRACE_STAGE.equals(oldContinueStage)
+                    && ContinueStageEnum.NORMAL_STAGE.equals(continueStageResult)) {
                     piStatus.setStageStartDate(punchInDate);
                     piStatus.setContinueInterruptedCount(0);
                 }
                 // 如果正常打卡期 变 惩罚期,则设置阶段开始时间和阶段结束时间,增加中断次数
-                if (ContinueStageEnum.NORMAL_STAGE.equals(oldContinueStage) && ContinueStageEnum.PENALTY_STAGE.equals(continueStageResult)) {
+                if (ContinueStageEnum.NORMAL_STAGE.equals(oldContinueStage)
+                    && ContinueStageEnum.PENALTY_STAGE.equals(continueStageResult)) {
                     piStatus.setStageStartDate(punchInDate);
                     piStatus.setStageEndDate(punchInDate.plusDays(piTask.getPenaltyDay()));
                     piStatus.setContinueInterruptedCount(piStatus.getContinueInterruptedCount() + 1);
                 }
                 // 如果惩罚期 变 正常打卡期,则设置阶段开始时间
-                if (ContinueStageEnum.PENALTY_STAGE.equals(oldContinueStage) && ContinueStageEnum.NORMAL_STAGE.equals(continueStageResult)) {
+                if (ContinueStageEnum.PENALTY_STAGE.equals(oldContinueStage)
+                    && ContinueStageEnum.NORMAL_STAGE.equals(continueStageResult)) {
                     piStatus.setStageStartDate(punchInDate);
                 }
 
+                // 周一或月初
+                if (isMonday || isFirstDayOfMonth) {
+                    piStatus.setRepeatCategory(piTask.getRepeatCategory());
+                    piStatus.setRepeatCustomDay(piTask.getRepeatCustomDay());
+                }
+
                 // 周一
                 if (isMonday) {
-                    String yearWeek = DateUtils.getYearWeek(punchInDate);
                     piStatus.setStatTimeInWeek(yearWeek);
 
-                    // TODO 需要考虑中途变换了重复频率的问题,增加一个记录实际值的字段,容错率也会跟着有影响,影响结算
-                    int PunchInTotalCountInWeek = punchInManager.getPunchInTotalCountInWeek(piTask, punchInDateStr);
+                    // 设置本周总打卡次数
+                    int PunchInTotalCountInWeek = punchInManager.getPunchInTotalCountInRange(piTask.getRepeatCategory(),
+                        piTask.getRepeatCustomDay(), DateUtils.getFirstDayOfWeek(punchInDate),
+                        DateUtils.getLastDayOfWeek(punchInDate));
                     piStatus.setPunchInTotalCountInWeek(PunchInTotalCountInWeek);
 
+                    // 重置数据
                     piStatus.setPunchInCountInWeek(0);
                     piStatus.setPunchInDoneCountInWeek(0);
+                    piStatus.setRepeatPrevTotalCountInWeek(0);
+                    piStatus.setRepeatStartDateInWeek(punchInDate);
                 }
 
                 // 打卡日所在月的第一天
                 if (isFirstDayOfMonth) {
-                    String yearMonth = DateUtils.getYearMonth(punchInDate);
                     piStatus.setStatTimeInMonth(yearMonth);
 
-                    // TODO 需要考虑中途变换了重复频率的问题
-                    int PunchInTotalCountInMonth = punchInManager.getPunchInTotalCountInMonth(piTask, punchInDateStr);
+                    // 设置本月总打卡次数
+                    int PunchInTotalCountInMonth = punchInManager.getPunchInTotalCountInRange(piTask.getRepeatCategory(),
+                            piTask.getRepeatCustomDay(), DateUtils.getFirstDayOfMonth(punchInDate),
+                            DateUtils.getLastDayOfMonth(punchInDate));
                     piStatus.setPunchInTotalCountInMonth(PunchInTotalCountInMonth);
 
+                    // 重置数据
                     piStatus.setPunchInCountInMonth(0);
                     piStatus.setPunchInDoneCountInMonth(0);
+                    piStatus.setRepeatPrevTotalCountInMonth(0);
+                    piStatus.setRepeatStartDateInMonth(punchInDate);
+                }
+
+                // 重复类型发生变换,总打卡次数=历史真实发生的总打卡次数+变换前发生的总打卡次数+变换后可能的总打卡次数
+                if (!piStatus.getRepeatCategory().equals(piTask.getRepeatCategory())) {
+                    // 历史真实发生的总打卡次数(周)
+                    Integer oldPrevTotalCountInWeek = Optional.ofNullable(piStatus.getRepeatPrevTotalCountInWeek()).orElse(0);
+                    // 变换前发生的总打卡次数(周)
+                    int prevTotalCountInWeek = punchInManager.getPunchInTotalCountInRange(piStatus.getRepeatCategory(),
+                            piStatus.getRepeatCustomDay(), piStatus.getRepeatStartDateInWeek(),
+                            punchInDate.minusDays(1));
+                    // 变换后可能的总打卡次数(周)
+                    int punchInTotalCountInWeek = punchInManager.getPunchInTotalCountInRange(piTask.getRepeatCategory(), piTask.getRepeatCustomDay(), punchInDate, DateUtils.getLastDayOfWeek(punchInDate));
+
+                    // 历史真实发生的总打卡次数(月)
+                    Integer oldPrevTotalCountInMonth = Optional.ofNullable(piStatus.getRepeatPrevTotalCountInMonth()).orElse(0);
+                    // 变换前发生的总打卡次数(月)
+                    int prevTotalCountInMonth = punchInManager.getPunchInTotalCountInRange(piStatus.getRepeatCategory(),
+                            piStatus.getRepeatCustomDay(), piStatus.getRepeatStartDateInMonth(),
+                            punchInDate.minusDays(1));
+                    // 变换后可能的总打卡次数(月 )
+                    int punchInTotalCountInMonth = punchInManager.getPunchInTotalCountInRange(piTask.getRepeatCategory(), piTask.getRepeatCustomDay(), punchInDate, DateUtils.getLastDayOfMonth(punchInDate));
+
+                    // 设置实时数据
+                    piStatus.setRepeatPrevTotalCountInWeek(prevTotalCountInWeek + oldPrevTotalCountInWeek);
+                    piStatus.setPunchInTotalCountInWeek(piStatus.getRepeatPrevTotalCountInWeek() + punchInTotalCountInWeek);
+                    piStatus.setRepeatPrevTotalCountInMonth(prevTotalCountInMonth + oldPrevTotalCountInMonth);
+                    piStatus.setPunchInTotalCountInMonth(piStatus.getRepeatPrevTotalCountInMonth() + punchInTotalCountInMonth);
                 }
 
                 // 存在打卡记录则已打卡数加1
@@ -240,9 +319,6 @@ public class PunchInCoreTask {
                     piStatus.setPunchInDoneCountInMonth(piStatus.getPunchInDoneCountInMonth() + 1);
                 }
 
-                // TODO 可以考虑把年数据一起进行统计
-                // TODO 可以考虑把统计数据一起落表
-
                 // 计算积分
                 int taskPoints = settleManager.calculatePointsInTask(piTask, piTaskExtList, piTaskHistory, piStatus);
                 piStatus.setPointsInWeek(piStatus.getPointsInWeek() + taskPoints);
@@ -253,35 +329,129 @@ public class PunchInCoreTask {
                 // 打卡记录 更新
                 updatePiTaskHistory.setSettlePoints(taskPoints);
                 updatePiTaskHistory.setSettleResult(SettleResultEnum.SETTLED);
-                updatePiTaskHistory.setSettleTaskHistoryId(piTaskData.getPiTask().getId());
+                updatePiTaskHistory.setSettlePiTaskId(piTask.getId());
+
+                addPiStatusHistories.add(piStatusHistory);
+                updatePiStatusList.add(piStatus);
                 updatePunchInTaskHistories.add(updatePiTaskHistory);
+                if (isSunday) {
+                    StatPiTaskWeek statPiTaskWeek = new StatPiTaskWeek();
+                    statPiTaskWeek.setUserId(punchInSettle.getUserId());
+                    statPiTaskWeek.setTaskUniqueId(piTask.getUniqueId());
+                    statPiTaskWeek.setStatTime(piStatus.getStatTimeInWeek());
+                    statPiTaskWeek.setPunchInTotalCount(piStatus.getPunchInTotalCountInWeek());
+                    statPiTaskWeek.setPunchInCount(piStatus.getPunchInCountInWeek());
+                    statPiTaskWeek.setPunchInDoneCount(piStatus.getPunchInDoneCountInWeek());
+                    statPiTaskWeek.setPoints(piStatus.getPointsInWeek());
+
+                    Integer punchInTotalCount = Optional.ofNullable(piStatus.getPunchInTotalCountInWeek()).orElse(0);
+                    if (punchInTotalCount == 0) {
+                        statPiTaskWeek.setPunchInRate(ZERO_RATE);
+                        statPiTaskWeek.setPunchInDoneRate(ZERO_RATE);
+                    } else {
+                        Integer punchInCount = Optional.ofNullable(piStatus.getPunchInCountInWeek()).orElse(0);
+                        Integer punchInDoneCount = Optional.ofNullable(piStatus.getPunchInDoneCountInWeek()).orElse(0);
+                        BigDecimal totalCount = new BigDecimal(punchInTotalCount);
+
+                        BigDecimal punchInRate = BigDecimal.valueOf(punchInCount).divide(totalCount, 2, RoundingMode.HALF_UP).multiply(ONE_HUNDRED);
+                        statPiTaskWeek.setPunchInRate(punchInRate);
+
+                        BigDecimal punchInDoneRate = BigDecimal.valueOf(punchInDoneCount).divide(totalCount, 2, RoundingMode.HALF_UP).multiply(ONE_HUNDRED);
+                        statPiTaskWeek.setPunchInDoneRate(punchInDoneRate);
+                    }
+
+                    addStatPiTaskWeekList.add(statPiTaskWeek);
+                }
+
+                if (isLastDayOfMonth) {
+                    StatPiTaskMonth statPiTaskMonth = new StatPiTaskMonth();
+                    statPiTaskMonth.setUserId(punchInSettle.getUserId());
+                    statPiTaskMonth.setTaskUniqueId(piTask.getUniqueId());
+                    statPiTaskMonth.setStatTime(piStatus.getStatTimeInMonth());
+                    statPiTaskMonth.setPunchInTotalCount(piStatus.getPunchInTotalCountInMonth());
+                    statPiTaskMonth.setPunchInCount(piStatus.getPunchInCountInMonth());
+                    statPiTaskMonth.setPunchInDoneCount(piStatus.getPunchInDoneCountInMonth());
+                    statPiTaskMonth.setPoints(piStatus.getPointsInMonth());
+
+                    Integer punchInTotalCount = Optional.ofNullable(piStatus.getPunchInTotalCountInMonth()).orElse(0);
+                    if (punchInTotalCount == 0) {
+                        statPiTaskMonth.setPunchInRate(ZERO_RATE);
+                        statPiTaskMonth.setPunchInDoneRate(ZERO_RATE);
+                    } else {
+                        Integer punchInCount = Optional.ofNullable(piStatus.getPunchInCountInMonth()).orElse(0);
+                        Integer punchInDoneCount = Optional.ofNullable(piStatus.getPunchInDoneCountInMonth()).orElse(0);
+                        BigDecimal totalCount = new BigDecimal(punchInTotalCount);
+
+                        BigDecimal punchInRate = BigDecimal.valueOf(punchInCount).divide(totalCount, 2, RoundingMode.HALF_UP).multiply(ONE_HUNDRED);
+                        statPiTaskMonth.setPunchInRate(punchInRate);
+
+                        BigDecimal punchInDoneRate = BigDecimal.valueOf(punchInDoneCount).divide(totalCount, 2, RoundingMode.HALF_UP).multiply(ONE_HUNDRED);
+                        statPiTaskMonth.setPunchInDoneRate(punchInDoneRate);
+                    }
+
+                    addStatPiTaskMonthList.add(statPiTaskMonth);
+                }
             }
 
+            PiMultiTask piMultiTask = punchInSettle.getPiMultiTask();
+            PiMultiTaskHistory piMultiTaskHistory = punchInSettle.getPiMultiTaskHistory();
+            PiStatus piStatus = punchInSettle.getPiStatus();
+
+            PiStatusHistory piStatusHistory =  new PiStatusHistory();
+            BeanUtils.copyProperties(piStatus, piStatusHistory);
+            addPiStatusHistories.add(piStatusHistory);
+
             // 多任务处理部分
             PiMultiTaskHistory updatePiMultiTaskHistory = new PiMultiTaskHistory();
 
             // 判断多任务打卡状态并设置
-            PunchInResultEnum punchInResultEnumResult = punchInManager.judgePunchInResultInMultiTask(punchInSettle.getPiMultiTask(),
-                    punchInSettle.getRelaPunchInTaskHistories());
-            punchInSettle.getPiMultiTaskHistory().setPunchInStatus(punchInResultEnumResult);
-            updatePiMultiTaskHistory.setPunchInStatus(punchInResultEnumResult);
-
-            int multiTaskPoints = settleManager.calculatePointsInMultiTask(punchInSettle.getPiMultiTask(),
-                    punchInSettle.getPiMultiTaskExtList(), punchInSettle.getPiMultiTaskHistory(),
-                    punchInSettle.getPiMultiTask());
+            PunchInResultEnum punchInResult = punchInManager.judgePunchInResultInMultiTask(piMultiTask, punchInSettle.getRelaPunchInTaskHistories());
+            piMultiTaskHistory.setPunchInResult(punchInResult);
+            updatePiMultiTaskHistory.setPunchInResult(punchInResult);
+
+            // 设置统计时间
+            piStatus.setStatusDate(punchInDateStr);
+            // 设置任务连续状态
+            ContinueStatusEnum oldTaskContinueStatus = piStatus.getTaskContinueStatus();
+            piStatus.setTaskContinueStatus(punchInResult.equals(PunchInResultEnum.DONE)
+                    ? ContinueStatusEnum.CONTINUE : ContinueStatusEnum.INTERRUPTED);
+            piStatus.setTaskContinueDay(oldTaskContinueStatus.equals(piStatus.getTaskContinueStatus())
+                    ? piStatus.getTaskContinueDay() + 1 : 1);
+
+            int multiTaskPoints = settleManager.calculatePointsInMultiTask(piMultiTask,
+                punchInSettle.getPiMultiTaskExtList(), piMultiTaskHistory,
+                punchInSettle.getPiStatus());
             updatePiMultiTaskHistory.setSettlePoints(multiTaskPoints);
+            updatePiMultiTaskHistory.setSettleResult(SettleResultEnum.SETTLED);
 
-            // TODO 要判断并设置结算状态
             // TODO 要设置结算任务执行ID
             updatePunchInMultiTaskHistories.add(updatePiMultiTaskHistory);
         }
 
-        punchInTaskHistoryService.batchUpdate(updatePunchInTaskHistories);
-        punchInMultiTaskHistoryService.batchUpdate(updatePunchInMultiTaskHistories);
+        // 数据入库
+        if (!CollectionUtils.isEmpty(addPiStatusHistories)) {
+            piStatusHistoryService.insertList(addPiStatusHistories);
+        }
+        if (!CollectionUtils.isEmpty(addStatPiTaskWeekList)) {
+            statPiTaskWeekService.insertList(addStatPiTaskWeekList);
+        }
+        if (!CollectionUtils.isEmpty(addStatPiTaskMonthList)) {
+            statPiTaskMonthService.insertList(addStatPiTaskMonthList);
+        }
+        if (!CollectionUtils.isEmpty(updatePiStatusList)) {
+            piStatusService.batchUpdate(updatePiStatusList);
+        }
+        if (!CollectionUtils.isEmpty(updatePunchInTaskHistories)) {
+            piTaskHistoryService.batchUpdate(updatePunchInTaskHistories);
+        }
+        if (!CollectionUtils.isEmpty(updatePunchInMultiTaskHistories)) {
+            piMultiTaskHistoryService.batchUpdate(updatePunchInMultiTaskHistories);
+        }
     }
 
     /**
      * 获取用户ID-打卡结算数据关联
+     * 
      * @param userIds 设计的用户
      * @param punchInDateStr 打卡日期
      * @return
@@ -294,8 +464,9 @@ public class PunchInCoreTask {
         PiMultiTaskQuery piMultiTaskQuery = new PiMultiTaskQuery();
         piMultiTaskQuery.setMultiTaskTaskStatus(ArchiveStatusEnum.ACTIVE);
         piMultiTaskQuery.setUserIds(userIds);
-        List<PiMultiTask> piMultiTasks = punchInMultiTaskService.queryByCondition(piMultiTaskQuery);
-        Map<Long, PiMultiTask> punchInMultiTaskMap = piMultiTasks.stream().collect(Collectors.toMap(PiMultiTask::getUserId, Function.identity(), (key1, key2) -> key1));
+        List<PiMultiTask> piMultiTasks = piMultiTaskService.queryByCondition(piMultiTaskQuery);
+        Map<Long, PiMultiTask> punchInMultiTaskMap = piMultiTasks.stream()
+            .collect(Collectors.toMap(PiMultiTask::getUserId, Function.identity(), (key1, key2) -> key1));
 
         // 多任务ID
         Set<Long> multiTaskIds = piMultiTasks.stream().map(PiMultiTask::getId).collect(Collectors.toSet());
@@ -305,39 +476,47 @@ public class PunchInCoreTask {
         // 获取多任务拓展信息,多任务ID-多任务拓展关联
         PiMultiTaskExtQuery piMultiTaskExtQuery = new PiMultiTaskExtQuery();
         piMultiTaskExtQuery.setMultiTaskIds(multiTaskIds);
-        List<PiMultiTaskExt> piMultiTaskExtList = punchInMultiTaskExtService.queryByCondition(piMultiTaskExtQuery);
-        Map<Long, List<PiMultiTaskExt>> punchInMultiTaskExtMap = piMultiTaskExtList.stream().collect(Collectors.groupingBy(PiMultiTaskExt::getMultiTaskId));
+        List<PiMultiTaskExt> piMultiTaskExtList = piMultiTaskExtService.queryByCondition(piMultiTaskExtQuery);
+        Map<Long, List<PiMultiTaskExt>> punchInMultiTaskExtMap =
+            piMultiTaskExtList.stream().collect(Collectors.groupingBy(PiMultiTaskExt::getMultiTaskId));
 
         // 获取多任务打卡历史信息,多任务唯一ID-多任务打卡历史关联
         PiMultiTaskHistoryQuery piMultiTaskHistoryQuery = new PiMultiTaskHistoryQuery();
         piMultiTaskHistoryQuery.setPunchInMultiTaskUniqueIds(multiTaskUniqueIds);
         piMultiTaskHistoryQuery.setPunchInDate(punchInDateStr);
-        List<PiMultiTaskHistory> punchInMultiTaskHistories = punchInMultiTaskHistoryService.queryByCondition(piMultiTaskHistoryQuery);
-        Map<Long, PiMultiTaskHistory> punchInMultiTaskHistoryMap = punchInMultiTaskHistories.stream().collect(Collectors.toMap(PiMultiTaskHistory::getMultiTaskUniqueId, Function.identity(), (key1, key2)->key1));
+        List<PiMultiTaskHistory> punchInMultiTaskHistories =
+            piMultiTaskHistoryService.queryByCondition(piMultiTaskHistoryQuery);
+        Map<Long, PiMultiTaskHistory> punchInMultiTaskHistoryMap = punchInMultiTaskHistories.stream().collect(
+            Collectors.toMap(PiMultiTaskHistory::getMultiTaskUniqueId, Function.identity(), (key1, key2) -> key1));
 
         // 打卡任务状态,用户ID-打卡状态关联
         PiStatusQuery piStatusQuery = new PiStatusQuery();
         piStatusQuery.setUserIds(userIds);
-        List<PiStatus> piStatusList = punchInStatusService.queryByCondition(piStatusQuery);
-        Map<Long, List<PiStatus>> punchInStatusMap = piStatusList.stream().collect(Collectors.groupingBy(PiStatus::getUserId));
+        List<PiStatus> piStatusList = piStatusService.queryByCondition(piStatusQuery);
+        Map<Long, List<PiStatus>> punchInStatusMap =
+            piStatusList.stream().collect(Collectors.groupingBy(PiStatus::getUserId));
 
         // 多任务关联打卡任务,多任务ID-多任务关联打卡任务关联
-        List<PiMultiTaskRela> piMultiTaskRelaList = punchInMultiTaskRelaService.queryByMultiTaskId(multiTaskIds);
-        Map<Long, List<PiMultiTaskRela>> punchInMultiTaskRelaMap = piMultiTaskRelaList.stream().collect(Collectors.groupingBy(PiMultiTaskRela::getPunchInMultiTaskId));
+        List<PiMultiTaskRela> piMultiTaskRelaList = piMultiTaskRelaService.queryByMultiTaskId(multiTaskIds);
+        Map<Long, List<PiMultiTaskRela>> punchInMultiTaskRelaMap =
+            piMultiTaskRelaList.stream().collect(Collectors.groupingBy(PiMultiTaskRela::getMultiTaskId));
 
         // 获取打卡任务信息,打卡任务唯一ID-打卡任务关联
         PiTaskQuery piTaskQuery = new PiTaskQuery();
         piTaskQuery.setTaskStatus(ArchiveStatusEnum.ACTIVE);
+        piTaskQuery.setArchiveStatus(ArchiveStatusEnum.ACTIVE);
         piTaskQuery.setUserIds(userIds);
-        List<PiTask> piTasks = punchInTaskService.queryByCondition(piTaskQuery);
-        Map<Long, PiTask> punchInTaskMap = piTasks.stream().collect(Collectors.toMap(PiTask::getUniqueId, Function.identity(), (key1, key2) -> key1));
+        List<PiTask> piTasks = piTaskService.queryByCondition(piTaskQuery);
+        Map<Long, PiTask> punchInTaskMap =
+            piTasks.stream().collect(Collectors.toMap(PiTask::getUniqueId, Function.identity(), (key1, key2) -> key1));
 
         // 获取打卡记录,用户ID-打卡记录关联
         PiTaskHistoryQuery piTaskHistoryQuery = new PiTaskHistoryQuery();
         piTaskHistoryQuery.setPunchInDate(punchInDateStr);
         piTaskHistoryQuery.setUserIds(userIds);
-        List<PiTaskHistory> punchInTaskHistories = punchInTaskHistoryService.queryByCondition(piTaskHistoryQuery);
-        Map<Long, List<PiTaskHistory>> punchInTaskHistoryMap = punchInTaskHistories.stream().collect(Collectors.groupingBy(PiTaskHistory::getUserId));
+        List<PiTaskHistory> punchInTaskHistories = piTaskHistoryService.queryByCondition(piTaskHistoryQuery);
+        Map<Long, List<PiTaskHistory>> punchInTaskHistoryMap =
+            punchInTaskHistories.stream().collect(Collectors.groupingBy(PiTaskHistory::getUserId));
 
         // 打卡任务ID
         Set<Long> punchInTaskIds = piTasks.stream().map(PiTask::getId).collect(Collectors.toSet());
@@ -345,8 +524,9 @@ public class PunchInCoreTask {
         // 获取打卡任务拓展表,打卡任务ID-打卡任务拓展关联
         PiTaskExtQuery piTaskExtQuery = new PiTaskExtQuery();
         piTaskExtQuery.setPunchInTaskIds(punchInTaskIds);
-        List<PiTaskExt> piTaskExtList = punchInTaskExtService.queryByCondition(piTaskExtQuery);
-        Map<Long, List<PiTaskExt>> punchInTaskExtGroupList = piTaskExtList.stream().collect(Collectors.groupingBy(PiTaskExt::getPunchInTaskId));
+        List<PiTaskExt> piTaskExtList = piTaskExtService.queryByCondition(piTaskExtQuery);
+        Map<Long, List<PiTaskExt>> punchInTaskExtGroupList =
+            piTaskExtList.stream().collect(Collectors.groupingBy(PiTaskExt::getTaskId));
 
         return userIds.stream().map(userId -> {
             PunchInSettleData punchInSettleData = new PunchInSettleData();
@@ -362,13 +542,17 @@ public class PunchInCoreTask {
             punchInSettleData.setPiMultiTaskHistory(piMultiTaskHistory);
 
             List<PiStatus> tempPiStatusList = punchInStatusMap.get(userId);
-            PiStatus piStatusInMultiTask = tempPiStatusList.stream().filter(v -> Objects.nonNull(v.getMultiTaskUniqueId())).findFirst().get();
+            PiStatus piStatusInMultiTask =
+                tempPiStatusList.stream().filter(v -> Objects.nonNull(v.getMultiTaskUniqueId())).findFirst().get();
             punchInSettleData.setPiStatus(piStatusInMultiTask);
 
             List<PiMultiTaskRela> tempPiMultiTaskRelaList = punchInMultiTaskRelaMap.get(piMultiTask.getId());
-            Set<Long> relaContainTaskIdList = tempPiMultiTaskRelaList.stream().map(PiMultiTaskRela::getTaskId).collect(Collectors.toSet());
+            Set<Long> relaContainTaskIdList =
+                tempPiMultiTaskRelaList.stream().map(PiMultiTaskRela::getTaskId).collect(Collectors.toSet());
 
-            Map<Long, PiStatus> punchInStatusInTaskMap = tempPiStatusList.stream().filter(v -> Objects.nonNull(v.getTaskUniqueId())).collect(Collectors.toMap(PiStatus::getTaskUniqueId, Function.identity(), (key1, key2) -> key1));
+            Map<Long, PiStatus> punchInStatusInTaskMap =
+                tempPiStatusList.stream().filter(v -> Objects.nonNull(v.getTaskUniqueId()))
+                    .collect(Collectors.toMap(PiStatus::getTaskUniqueId, Function.identity(), (key1, key2) -> key1));
 
             List<PiTaskHistory> tempPunchInTaskHistories = punchInTaskHistoryMap.get(userId);
             List<PiTaskData> piTaskDataList = new ArrayList<>(tempPunchInTaskHistories.size());

+ 76 - 17
src/main/java/com/punchsettle/server/utiis/DateUtils.java

@@ -1,9 +1,12 @@
 package com.punchsettle.server.utiis;
 
+import org.springframework.cglib.core.Local;
+
 import java.text.SimpleDateFormat;
 import java.time.DayOfWeek;
 import java.time.LocalDate;
 import java.time.format.DateTimeFormatter;
+import java.time.temporal.ChronoUnit;
 import java.time.temporal.TemporalAdjusters;
 import java.time.temporal.WeekFields;
 import java.util.ArrayList;
@@ -45,6 +48,64 @@ public class DateUtils {
         return new SimpleDateFormat(YYYY_MM_DD_FORMAT);
     }
 
+    /**
+     * 获取本周第一天(星期一)
+     * @param date
+     * @return
+     */
+    public static LocalDate getFirstDayOfWeek(LocalDate date) {
+        // 本身是第一天 直接返回
+        if (DayOfWeek.MONDAY.equals(date.getDayOfWeek())) {
+            return date;
+        }
+        // 获取本周的第一天(假设周一为一周的第一天)
+        return date.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
+    }
+
+    /**
+     * 获取本周最后一天(星期日)
+     * @param date
+     * @return
+     */
+    public static LocalDate getLastDayOfWeek(LocalDate date) {
+        // 本身是最后一天 直接返回
+        if (DayOfWeek.SUNDAY.equals(date.getDayOfWeek())) {
+            return date;
+        }
+
+        LocalDate firstDayOfWeek = getFirstDayOfWeek(date);
+        return firstDayOfWeek.plusDays(6);
+    }
+
+    /**
+     * 获取本月第一天
+     * @param date
+     * @return
+     */
+    public static LocalDate getFirstDayOfMonth(LocalDate date) {
+        // 本身是本月第一天直接返回
+        if (date.getDayOfMonth() == 1) {
+            return date;
+        }
+
+        return date.with(TemporalAdjusters.firstDayOfMonth());
+    }
+
+    /**
+     * 获取本月最后一天
+     * @param date
+     * @return
+     */
+    public static LocalDate getLastDayOfMonth(LocalDate date) {
+        // 本身是本月最后一天直接返回
+        if (date.getDayOfMonth() == date.lengthOfMonth()) {
+            return date;
+        }
+
+        LocalDate firstDayOfMonth = getFirstDayOfMonth(date);
+        return firstDayOfMonth.plusDays(date.lengthOfMonth() - 1);
+    }
+
     /**
      * 获取当前周的日期列表(周一~周日)
      * @return 返回日期字符串列表
@@ -60,16 +121,7 @@ public class DateUtils {
      * @return
      */
     public static List<LocalDate> getDateRangeInWeek(LocalDate date) {
-        // 获取本周的第一天(假设周一为一周的第一天)
-        LocalDate firstDayOfWeek = date.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
-
-        // 打印本周的所有日期
-        List<LocalDate> list = new ArrayList<>(7);
-        for (int i = 0; i < 7; i++) {
-            LocalDate tempDate = firstDayOfWeek.plusDays(i);
-            list.add(tempDate);
-        }
-        return list;
+        return getDateRange(getFirstDayOfWeek(date), getLastDayOfWeek(date));
     }
 
     /**
@@ -78,15 +130,22 @@ public class DateUtils {
      * @return
      */
     public static List<LocalDate> getDateRangeInMonth(LocalDate date) {
-        // 获取本月的第一天
-        LocalDate firstDayOfMonth = date.with(TemporalAdjusters.firstDayOfMonth());
-        // 本月长度
-        int lengthOfMonth = date.lengthOfMonth();
+        return getDateRange(getFirstDayOfMonth(date), getLastDayOfMonth(date));
+    }
 
+    /**
+     * 通过指定的日期范围获取日期列表
+     * @param startDate 开始日期(包含)
+     * @param endDate 结束日期(包含)
+     * @return
+     */
+    public static List<LocalDate> getDateRange(LocalDate startDate, LocalDate endDate) {
+        // 计算日期差(天数)
+        long daysBetween = ChronoUnit.DAYS.between(startDate, endDate.plusDays(1));
         // 打印本月的所有日期
-        List<LocalDate> list = new ArrayList<>(lengthOfMonth);
-        for (int i = 0; i < lengthOfMonth; i++) {
-            LocalDate tempDate = firstDayOfMonth.plusDays(i);
+        List<LocalDate> list = new ArrayList<>((int) daysBetween);
+        for (int i = 0; i < daysBetween; i++) {
+            LocalDate tempDate = startDate.plusDays(i);
             list.add(tempDate);
         }
         return list;