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

【feat】【v3】
1.修改表结构
2.完善结算逻辑
3.完善积分分发逻辑
4.修改表结构

ChenYL 10 месяцев назад
Родитель
Сommit
6b5fe5dd0a
37 измененных файлов с 1357 добавлено и 344 удалено
  1. 44 27
      doc/sql/update-v3.sql
  2. 65 47
      doc/技术文档.md
  3. 3 62
      src/main/java/com/punchsettle/server/atomic/entity/PiTaskHistory.java
  4. 77 0
      src/main/java/com/punchsettle/server/atomic/entity/SettleTaskRelaHistory.java
  5. 11 3
      src/main/java/com/punchsettle/server/atomic/entity/SettleUserHistory.java
  6. 0 15
      src/main/java/com/punchsettle/server/atomic/mapper/SettlePointsHistoryMapper.java
  7. 14 0
      src/main/java/com/punchsettle/server/atomic/mapper/SettleTaskRelaHistoryMapper.java
  8. 15 0
      src/main/java/com/punchsettle/server/atomic/mapper/SettleUserHistoryMapper.java
  9. 1 1
      src/main/java/com/punchsettle/server/atomic/service/IAccountTransferHistoryService.java
  10. 2 2
      src/main/java/com/punchsettle/server/atomic/service/IPiStatusHistoryService.java
  11. 0 28
      src/main/java/com/punchsettle/server/atomic/service/ISettlePointsHistoryService.java
  12. 14 0
      src/main/java/com/punchsettle/server/atomic/service/ISettleTaskHistoryService.java
  13. 20 0
      src/main/java/com/punchsettle/server/atomic/service/ISettleTaskRelaHistoryService.java
  14. 28 0
      src/main/java/com/punchsettle/server/atomic/service/ISettleUserHistoryService.java
  15. 5 4
      src/main/java/com/punchsettle/server/atomic/service/IUserService.java
  16. 1 1
      src/main/java/com/punchsettle/server/atomic/service/impl/AccountTransferHistoryServiceImpl.java
  17. 0 44
      src/main/java/com/punchsettle/server/atomic/service/impl/SettlePointsHistoryServiceImpl.java
  18. 19 0
      src/main/java/com/punchsettle/server/atomic/service/impl/SettleTaskHistoryServiceImpl.java
  19. 52 0
      src/main/java/com/punchsettle/server/atomic/service/impl/SettleUserHistoryServiceImpl.java
  20. 6 2
      src/main/java/com/punchsettle/server/atomic/service/impl/StatNewUserServiceImpl.java
  21. 5 2
      src/main/java/com/punchsettle/server/atomic/service/impl/StatPointsServiceImpl.java
  22. 12 4
      src/main/java/com/punchsettle/server/atomic/service/impl/UserServiceImpl.java
  23. 23 0
      src/main/java/com/punchsettle/server/constant/PointsDistributeStatusEnum.java
  24. 4 3
      src/main/java/com/punchsettle/server/constant/SettleResultEnum.java
  25. 2 1
      src/main/java/com/punchsettle/server/pojo/account/AccountQuery.java
  26. 57 0
      src/main/java/com/punchsettle/server/pojo/settle/SettleData.java
  27. 28 0
      src/main/java/com/punchsettle/server/pojo/settle/SettleUserHistoryQuery.java
  28. 8 0
      src/main/java/com/punchsettle/server/service/manager/ISettleManager.java
  29. 1 1
      src/main/java/com/punchsettle/server/service/manager/impl/AccountManagerImpl.java
  30. 33 12
      src/main/java/com/punchsettle/server/service/manager/impl/PunchInManagerImpl.java
  31. 29 29
      src/main/java/com/punchsettle/server/service/manager/impl/PunchInSettleManagerImpl.java
  32. 491 6
      src/main/java/com/punchsettle/server/service/manager/impl/SettleManagerImpl.java
  33. 30 0
      src/main/java/com/punchsettle/server/service/manager/impl/SettleTaskRelaHistoryServiceImpl.java
  34. 149 0
      src/main/java/com/punchsettle/server/task/PointsDistributeTask.java
  35. 85 0
      src/main/java/com/punchsettle/server/task/PointsSettleTask.java
  36. 0 50
      src/main/java/com/punchsettle/server/task/PunchInCoreTask.java
  37. 23 0
      src/main/java/com/punchsettle/server/task/StatNewUserTask.java

+ 44 - 27
doc/sql/update-v3.sql

@@ -302,17 +302,8 @@ CREATE TABLE `pi_task_history` (
   `punch_in_date` varchar(10) NOT NULL COMMENT '打卡日期',
   `count_track` int DEFAULT NULL COMMENT '次数记录',
   `time_track` time DEFAULT NULL COMMENT '时间记录',
-  `task_continue_status` varchar(20) DEFAULT NULL COMMENT '任务连续打卡状态(连续打卡-CONTINUE、中断-INTERRUPTED)',
-  `task_continue_day` int DEFAULT NULL COMMENT '任务连续天数,第一天开始就等于1',
-  `continue_stage` varchar(10) DEFAULT NULL COMMENT '连续阶段(宽限期-GRACE_STAGE,正常打卡期-NORMAL_STAGE,惩罚期-PENALTY_STAGE)',
-  `stage_start_date` date DEFAULT NULL COMMENT '阶段开始日期',
-  `stage_end_date` date DEFAULT NULL COMMENT '阶段结束日期',
-  `continue_interrupted_count` int DEFAULT NULL COMMENT '连续中断次数',
+  `task_id` bigint NOT NULL COMMENT '打卡时的打卡任务ID',
   `punch_in_result` varchar(10) DEFAULT NULL COMMENT '打卡状态(DONE-完成,UNDONE-未完成)',
-  `settle_result` varchar(20) NOT NULL COMMENT '结算结果(未结算-UNSETTLED,已结算-SETTLED)',
-  `settle_pi_task_id` bigint DEFAULT NULL COMMENT '结算时的打卡任务ID',
-  `settle_task_history_id` bigint DEFAULT NULL COMMENT '结算任务执行记录ID',
-  `settle_points` int DEFAULT NULL COMMENT '结算奖励积分',
   `created_by` bigint NOT NULL COMMENT '创建人',
   `creation_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
   `last_updated_by` bigint NOT NULL COMMENT '最后更新人',
@@ -370,8 +361,9 @@ CREATE TABLE `pi_status` (
   `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_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 '本周需打卡数',
@@ -436,12 +428,14 @@ CREATE TABLE `pi_status_history` (
   KEY `idx_PIStatusHis_StatusDate` (`status_date`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='打卡任务状态记录表';
 
-CREATE TABLE `settle_points_history` (
+CREATE TABLE `settle_user_history` (
   `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
   `settle_task_history_id` bigint NOT NULL COMMENT '结算任务执行ID',
   `user_id` bigint NOT NULL COMMENT '用户表主键',
   `settle_date` varchar(10) NOT NULL COMMENT '结算日期',
+  `settle_result` varchar(20) NOT NULL COMMENT '结算结果(已结算-SETTLED,撤销结算-REVOKE_SETTLED)',
   `settle_points` int NOT NULL COMMENT '结算积分',
+  `distribute_status` varchar(20) NOT NULL COMMENT '积分下发状态(已分发-DISTRIBUTE,未分发-NOT_DISTRIBUTE)',
   `before_settle_points` int NOT NULL COMMENT '结算前用户拥有的积分',
   `after_settle_points` int NOT NULL COMMENT '结算后用户拥有的积分',
   `created_by` bigint NOT NULL COMMENT '创建人',
@@ -454,7 +448,30 @@ CREATE TABLE `settle_points_history` (
   KEY `idx_SPointsHis_UserId` (`user_id`),
   KEY `idx_SPointsHis_SettleDate` (`settle_date`),
   KEY `idx_SPointsHis_STaskHisId` (`settle_task_history_id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='结算积分记录表';
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='结算用户记录表';
+
+CREATE TABLE `settle_task_rela_history` (
+  `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
+  `settle_task_history_id` bigint NOT NULL COMMENT '结算任务执行ID',
+  `settle_user_history_id` bigint NOT NULL COMMENT '结算用户记录id',
+  `user_id` bigint NOT NULL COMMENT '用户表主键',
+  `settle_date` varchar(10) NOT NULL COMMENT '结算日期',
+  `pi_task_id` bigint NOT NULL COMMENT '单任务ID',
+  `pi_task_unique_id` bigint NOT NULL COMMENT '单任务唯一ID',
+  `pi_task_history_id` bigint NOT NULL COMMENT '单任务打卡记录ID',
+  `settle_result` varchar(20) NOT NULL COMMENT '结算结果(已结算-SETTLED,无需结算-NOT_SETTLED)',
+  `settle_points` int NOT NULL default 0 COMMENT '结算积分',
+  `created_by` bigint NOT NULL COMMENT '创建人',
+  `creation_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+  `last_updated_by` bigint NOT NULL COMMENT '最后更新人',
+  `last_update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后更新时间',
+  `version` bigint NOT NULL DEFAULT '1' COMMENT '版本号',
+  `delete_flag` tinyint NOT NULL DEFAULT '0' COMMENT '逻辑删除标志(0-未删除,1-已删除)',
+  PRIMARY KEY (`id`),
+  KEY `idx_SPointsHis_UserId` (`user_id`),
+  KEY `idx_SPointsHis_SettleDate` (`settle_date`),
+  KEY `idx_SPointsHis_STaskHisId` (`settle_task_history_id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci COMMENT='结算任务关联记录表';
 
 CREATE TABLE `sys_calendar` (
   `id` bigint NOT NULL AUTO_INCREMENT COMMENT '主键',
@@ -647,11 +664,11 @@ ALTER TABLE punch_settle.settle_task_history DROP COLUMN error_message;
 ALTER TABLE punch_settle.settle_task_history CHANGE processed_num processed_total_num int DEFAULT 0 NOT NULL COMMENT '待处理结算数量';
 ALTER TABLE punch_settle.settle_task_history MODIFY COLUMN processed_total_num int DEFAULT 0 NOT NULL COMMENT '待处理总结算数量';
 
-INSERT INTO punch_settle.settle_points_history(id, settle_task_history_id, user_id, settle_date, settle_points, before_settle_points, after_settle_points, created_by, creation_time, last_updated_by, last_update_time, version, delete_flag)
-SELECT pis.id, settlement_task_id, user_id, sth.settle_date , settle_reward_num, before_settle_reward_num, after_settle_reward_num, pis.created_by, pis.creation_time, pis.last_updated_by, pis.last_update_time, pis.version, pis.delete_flag
-FROM punch_in_settlement pis
-left join settle_task_history sth on pis.settlement_task_id = sth.id;
-DROP TABLE IF EXISTS punch_in_settlement;
+-- INSERT INTO punch_settle.settle_points_history(id, settle_task_history_id, user_id, settle_date, settle_points, before_settle_points, after_settle_points, created_by, creation_time, last_updated_by, last_update_time, version, delete_flag)
+-- SELECT pis.id, settlement_task_id, user_id, sth.settle_date , settle_reward_num, before_settle_reward_num, after_settle_reward_num, pis.created_by, pis.creation_time, pis.last_updated_by, pis.last_update_time, pis.version, pis.delete_flag
+-- FROM punch_in_settlement pis
+-- left join settle_task_history sth on pis.settlement_task_id = sth.id;
+-- DROP TABLE IF EXISTS punch_in_settlement;
 
 -- 删除无效的用户数据
 delete from user where id not in (select created_by from pi_task group by created_by);
@@ -684,15 +701,15 @@ created_by, creation_time, last_updated_by, last_update_time, version, delete_fl
 from user_claim_reward_record rr;
 DROP TABLE IF EXISTS user_claim_reward_record;
 
-insert into pi_task_history(id, user_id, task_unique_id,
-punch_in_date, punch_in_result, count_track, time_track, settle_task_history_id,
-settle_result, settle_pi_task_id, created_by, creation_time,
-last_updated_by, last_update_time, version, delete_flag)
-select pir.id, pir.created_by, punch_in_id, punch_in_date, punch_in_status,
-count_track, time_track, pirsr.settlement_id , 'SETTLED', pir.punch_in_id , pir.created_by,
-pir.creation_time, pir.last_updated_by, pir.last_update_time, pir.version, pir.delete_flag
-from punch_in_record pir
-left join punch_in_record_settlement_rela pirsr on pir.id = pirsr.record_id;
+-- insert into pi_task_history(id, user_id, task_unique_id,
+-- punch_in_date, punch_in_result, count_track, time_track, settle_task_history_id,
+-- settle_result, settle_pi_task_id, created_by, creation_time,
+-- last_updated_by, last_update_time, version, delete_flag)
+-- select pir.id, pir.created_by, punch_in_id, punch_in_date, punch_in_status,
+-- count_track, time_track, pirsr.settlement_id , 'SETTLED', pir.punch_in_id , pir.created_by,
+-- pir.creation_time, pir.last_updated_by, pir.last_update_time, pir.version, pir.delete_flag
+-- from punch_in_record pir
+-- left join punch_in_record_settlement_rela pirsr on pir.id = pirsr.record_id;
 
 update pi_task_history set punch_in_result = 'DONE' where punch_in_result = '3';
 update pi_task_history set punch_in_result = 'DONE' where punch_in_result = '1';

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

@@ -738,31 +738,22 @@ ui设计工具:即时设计
 
 表名:pi_task_history
 
-| 字段                       | 类型        | 描述                                                         | 索引     |
-| -------------------------- | ----------- | ------------------------------------------------------------ | -------- |
-| id                         | bigint      | 主键                                                         | 主键索引 |
-| user_id                    | bigint      | 用户ID                                                       | 普通索引 |
-| task_unique_id             | bigint      | 打卡任务唯一ID                                               | 普通索引 |
-| punch_in_date              | varchar(10) | 打卡日期                                                     | 普通索引 |
-| count_track                | int         | 次数记录                                                     |          |
-| time_track                 | time        | 时间记录                                                     |          |
-| 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         | 连续中断次数                                                 |          |
-| punch_in_result            | varchar(10) | 打卡结果(DONE-完成,UNDONE-未完成)                           |          |
-| settle_result              | varchar(10) | 结算结果(未结算-UNSETTLED,已结算-SETTLED)                 |          |
-| settle_pi_task_id          | bigint      | 结算时的打卡任务ID                                           |          |
-| settle_task_history_id     | bigint      | 结算任务执行记录ID                                           | 普通索引 |
-| settle_points              | 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                             | 普通索引 |
+| task_unique_id   | bigint      | 打卡任务唯一ID                     | 普通索引 |
+| punch_in_date    | varchar(10) | 打卡日期                           | 普通索引 |
+| count_track      | int         | 次数记录                           |          |
+| time_track       | time        | 时间记录                           |          |
+| task_id          | bigint      | 打卡任务ID                         |          |
+| punch_in_result  | varchar(10) | 打卡结果(DONE-完成,UNDONE-未完成) |          |
+| created_by       | bigint      | 创建人                             |          |
+| creation_time    | timestamp   | 创建时间                           | 普通索引 |
+| last_updated_by  | bigint      | 最后更新人                         |          |
+| last_update_time | timestamp   | 最后更新时间                       |          |
+| version          | bigint      | 版本号                             |          |
+| delete_flag      | tinyint     | 逻辑删除标志(0-未删除,1-已删除) |          |
 
 
 
@@ -890,28 +881,6 @@ ui设计工具:即时设计
 
 
 
-### 结算积分记录表
-
-表名:settle_points_history
-
-| 字段                   | 类型        | 描述                               | 索引     |
-| ---------------------- | ----------- | ---------------------------------- | -------- |
-| id                     | bigint      | 主键                               | 主键索引 |
-| settle_task_history_id | bigint      | 结算任务执行记录ID                 | 普通索引 |
-| user_id                | bigint      | 用户表主键                         | 普通索引 |
-| settle_date            | varchar(10) | 结算日期                           | 普通索引 |
-| settle_points          | int         | 结算积分                           |          |
-| before_settle_points   | int         | 结算前用户拥有的积分               |          |
-| after_settle_points    | int         | 结算后用户拥有的积分               |          |
-| created_by             | bigint      | 创建人                             |          |
-| creation_time          | timestamp   | 创建时间                           |          |
-| last_updated_by        | bigint      | 最后更新人                         |          |
-| last_update_time       | timestamp   | 最后更新时间                       |          |
-| version                | bigint      | 版本号                             |          |
-| delete_flag            | tinyint     | 逻辑删除标志(0-未删除,1-已删除) |          |
-
-
-
 ### 结算任务执行记录表
 
 表名:settle_task_history
@@ -932,6 +901,55 @@ ui设计工具:即时设计
 
 
 
+### 结算用户记录表
+
+表名:settle_user_history
+
+| 字段                   | 类型        | 描述                                                     | 索引     |
+| ---------------------- | ----------- | -------------------------------------------------------- | -------- |
+| id                     | bigint      | 主键                                                     | 主键索引 |
+| settle_task_history_id | bigint      | 结算任务执行记录ID                                       | 普通索引 |
+| user_id                | bigint      | 用户表主键                                               | 普通索引 |
+| settle_date            | varchar(10) | 结算日期                                                 | 普通索引 |
+| settle_points          | int         | 总结算积分                                               |          |
+| before_settle_points   | int         | 结算前用户拥有的积分                                     |          |
+| after_settle_points    | int         | 结算后用户拥有的积分                                     |          |
+| settle_result          | varchar(20) | 结算结果(已结算-SETTLED,撤销结算-REVOKE_SETTLED)      |          |
+| distribute_status      | varchar(20) | 积分下发状态(已分发-DISTRIBUTE,未分发-NOT_DISTRIBUTE) |          |
+| created_by             | bigint      | 创建人                                                   |          |
+| creation_time          | timestamp   | 创建时间                                                 |          |
+| last_updated_by        | bigint      | 最后更新人                                               |          |
+| last_update_time       | timestamp   | 最后更新时间                                             |          |
+| version                | bigint      | 版本号                                                   |          |
+| delete_flag            | tinyint     | 逻辑删除标志(0-未删除,1-已删除)                       |          |
+
+
+
+### 结算任务关联记录表
+
+表名:settle_task_rela_history
+
+| 字段                   | 类型        | 描述                                             | 索引     |
+| ---------------------- | ----------- | ------------------------------------------------ | -------- |
+| id                     | bigint      | 主键                                             | 主键索引 |
+| settle_task_history_id | bigint      | 结算任务执行记录ID                               | 普通索引 |
+| settle_user_history_id | bigint      | 结算用户记录id                                   | 普通索引 |
+| user_id                | bigint      | 用户表主键                                       | 普通索引 |
+| settle_date            | varchar(10) | 结算日期                                         | 普通索引 |
+| pi_task_id             | bigint      | 单任务ID                                         |          |
+| pi_task_unique_id      | bigint      | 单任务唯一ID                                     |          |
+| pi_task_history_id     | bigint      | 单任务打卡记录ID                                 |          |
+| settle_result          | varchar(20) | 结算结果(已结算-SETTLED,无需结算-NOT_SETTLED) |          |
+| settle_points          | int         | 结算积分                                         |          |
+| created_by             | bigint      | 创建人                                           |          |
+| creation_time          | timestamp   | 创建时间                                         |          |
+| last_updated_by        | bigint      | 最后更新人                                       |          |
+| last_update_time       | timestamp   | 最后更新时间                                     |          |
+| version                | bigint      | 版本号                                           |          |
+| delete_flag            | tinyint     | 逻辑删除标志(0-未删除,1-已删除)               |          |
+
+
+
 ### 系统字典表
 
 表名:sys_dict

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

@@ -60,44 +60,11 @@ public class PiTaskHistory extends BaseEntity implements Serializable {
     @Column(name = "time_track")
     private LocalTime timeTrack;
 
-
-    /**
-     * 任务连续打卡状态(连续打卡-CONTINUE、中断-INTERRUPTED)
-     * @see ContinueStatusEnum
-     */
-    @Column(name = "task_continue_status")
-    private ContinueStatusEnum taskContinueStatus;
-
     /**
-     * 任务连续天数,第一天开始就等于1
+     * 打卡时的打卡任务ID
      */
-    @Column(name = "task_continue_day")
-    private Integer taskContinueDay;
-
-    /**
-     * 连续阶段(宽限期-GRACE_STAGE,正常打卡期-NORMAL_STAGE,惩罚期-PENALTY_STAGE)
-     * @see ContinueStageEnum
-     */
-    @Column(name = "continue_stage")
-    private ContinueStageEnum continueStage;
-
-    /**
-     * 阶段开始日期
-     */
-    @Column(name = "stage_start_date")
-    private LocalDate stageStartDate;
-
-    /**
-     * 阶段结束日期
-     */
-    @Column(name = "stage_end_date")
-    private LocalDate stageEndDate;
-
-    /**
-     * 连续中断次数
-     */
-    @Column(name = "continue_interrupted_count")
-    private Integer continueInterruptedCount;
+    @Column(name = "task_id")
+    private Long taskId;
 
     /**
      * 打卡结果(DONE-完成,UNDONE-未完成)
@@ -105,30 +72,4 @@ public class PiTaskHistory extends BaseEntity implements Serializable {
      */
     @Column(name = "punch_in_result")
     private PunchInResultEnum punchInResult;
-
-    /**
-     * 结算结果(未结算-UNSETTLED,已结算-SETTLED)
-     * @see SettleResultEnum
-     */
-    @Column(name = "settle_result")
-    private SettleResultEnum settleResult;
-
-    /**
-     * 结算任务执行ID
-     */
-    @Column(name = "settle_task_history_id")
-    private Long settleTaskHistoryId;
-
-    /**
-     * 结算时的打卡任务ID
-     */
-    @Column(name = "settle_pi_task_id")
-    private Long settlePiTaskId;
-
-    /**
-     * 结算奖励积分
-     */
-    @Column(name = "settle_points")
-    private Integer settlePoints;
-
 }

+ 77 - 0
src/main/java/com/punchsettle/server/atomic/entity/SettleTaskRelaHistory.java

@@ -0,0 +1,77 @@
+package com.punchsettle.server.atomic.entity;
+
+import com.punchsettle.server.common.pojo.BaseEntity;
+import com.punchsettle.server.constant.SettleResultEnum;
+import jakarta.persistence.Column;
+import jakarta.persistence.Table;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+import java.io.Serializable;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @date 2025/5/6 16:38
+ * @description 结算任务关联记录表
+ */
+@Data
+@EqualsAndHashCode(callSuper = true)
+@Table(name = "settle_task_rela_history")
+public class SettleTaskRelaHistory extends BaseEntity implements Serializable {
+
+    /**
+     * 结算任务执行记录ID
+     */
+    @Column(name = "settle_task_history_id")
+    private Long settleTaskHistoryId;
+
+    /**
+     * 结算用户记录id
+     */
+    @Column(name = "settle_user_history_id")
+    private Long settleUserHistoryId;
+
+    /**
+     * 用户表主键
+     */
+    @Column(name = "user_id")
+    private Long userId;
+
+    /**
+     * 结算日期
+     */
+    @Column(name = "settle_date")
+    private String settleDate;
+
+    /**
+     * 单任务ID
+     */
+    @Column(name = "pi_task_id")
+    private Long piTaskId;
+
+    /**
+     * 单任务唯一ID
+     */
+    @Column(name = "pi_task_unique_id")
+    private Long piTaskUniqueId;
+
+    /**
+     * 单任务打卡记录ID
+     */
+    @Column(name = "pi_task_history_id")
+    private Long piTaskHistoryId;
+
+    /**
+     * 结算结果(已结算-SETTLED,无需结算-NOT_SETTLED)
+     * @see SettleResultEnum
+     */
+    @Column(name = "settle_result")
+    private SettleResultEnum settleResult;
+
+    /**
+     * 结算积分
+     */
+    @Column(name = "settle_points")
+    private Integer settlePoints;
+}

+ 11 - 3
src/main/java/com/punchsettle/server/atomic/entity/SettlePointsHistory.java → src/main/java/com/punchsettle/server/atomic/entity/SettleUserHistory.java

@@ -5,6 +5,7 @@ import java.io.Serializable;
 
 import com.punchsettle.server.common.pojo.BaseEntity;
 
+import com.punchsettle.server.constant.PointsDistributeStatusEnum;
 import jakarta.persistence.Column;
 import jakarta.persistence.Table;
 import lombok.Data;
@@ -17,13 +18,13 @@ import lombok.EqualsAndHashCode;
 /**
  * @author tyuio
  * @version 1.0.0
- * @description 结算积分记录表
+ * @description 结算用户记录表
  * @date 2025/04/08 09:49
  */
 @Data
 @EqualsAndHashCode(callSuper = true)
-@Table(name = "settle_points_history")
-public class SettlePointsHistory extends BaseEntity implements Serializable {
+@Table(name = "settle_user_history")
+public class SettleUserHistory extends BaseEntity implements Serializable {
 
     @Serial
     private static final long serialVersionUID = -9148914013607322749L;
@@ -64,4 +65,11 @@ public class SettlePointsHistory extends BaseEntity implements Serializable {
     @Column(name = "after_settle_points")
     private Integer afterSettlePoints;
 
+    /**
+     * 积分下发状态
+     * @see PointsDistributeStatusEnum
+     */
+    @Column(name="distribute_status")
+    private PointsDistributeStatusEnum distributeStatusEnum;
+
 }

+ 0 - 15
src/main/java/com/punchsettle/server/atomic/mapper/SettlePointsHistoryMapper.java

@@ -1,15 +0,0 @@
-package com.punchsettle.server.atomic.mapper;
-
-import com.punchsettle.server.atomic.entity.SettlePointsHistory;
-import tk.mybatis.mapper.common.Mapper;
-import tk.mybatis.mapper.common.special.InsertListMapper;
-
-/**
- * @author tyuio
- * @version 1.0.0
- * @description 结算积分记录表 Mapper
- * @date 2025/04/08 10:30
- */
-public interface SettlePointsHistoryMapper extends Mapper<SettlePointsHistory>, InsertListMapper<SettlePointsHistory> {
-
-}

+ 14 - 0
src/main/java/com/punchsettle/server/atomic/mapper/SettleTaskRelaHistoryMapper.java

@@ -0,0 +1,14 @@
+package com.punchsettle.server.atomic.mapper;
+
+import com.punchsettle.server.atomic.entity.SettleTaskRelaHistory;
+import tk.mybatis.mapper.common.Mapper;
+import tk.mybatis.mapper.common.special.InsertListMapper;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @date 2025/5/6 18:03
+ * @description 结算任务关联记录表
+ */
+public interface SettleTaskRelaHistoryMapper extends Mapper<SettleTaskRelaHistory>, InsertListMapper<SettleTaskRelaHistory> {
+}

+ 15 - 0
src/main/java/com/punchsettle/server/atomic/mapper/SettleUserHistoryMapper.java

@@ -0,0 +1,15 @@
+package com.punchsettle.server.atomic.mapper;
+
+import com.punchsettle.server.atomic.entity.SettleUserHistory;
+import tk.mybatis.mapper.common.Mapper;
+import tk.mybatis.mapper.common.special.InsertListMapper;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @description 结算用户记录表 Mapper
+ * @date 2025/04/08 10:30
+ */
+public interface SettleUserHistoryMapper extends Mapper<SettleUserHistory>, InsertListMapper<SettleUserHistory> {
+
+}

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

@@ -16,7 +16,7 @@ public interface IAccountTransferHistoryService {
      * 批量插入
      * @param accountTransferHistories
      */
-    void batchInsert(List<AccountTransferHistory> accountTransferHistories);
+    void insertList(List<AccountTransferHistory> accountTransferHistories);
 
     /**
      * 查询账户转账记录

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

@@ -1,9 +1,9 @@
 package com.punchsettle.server.atomic.service;
 
-import com.punchsettle.server.atomic.entity.PiStatusHistory;
-
 import java.util.List;
 
+import com.punchsettle.server.atomic.entity.PiStatusHistory;
+
 /**
  * @author tyuio
  * @version 1.0.0

+ 0 - 28
src/main/java/com/punchsettle/server/atomic/service/ISettlePointsHistoryService.java

@@ -1,28 +0,0 @@
-package com.punchsettle.server.atomic.service;
-
-import com.punchsettle.server.atomic.entity.SettlePointsHistory;
-
-import java.util.List;
-
-/**
- * @author tyuio
- * @version 1.0.0
- * @date 2025/4/8 10:38
- * @description 结算积分记录表 service
- */
-public interface ISettlePointsHistoryService {
-
-    /**
-     * 批量新增
-     * @param settlePointsHistories
-     */
-    void insertList(List<SettlePointsHistory> settlePointsHistories);
-
-    /**
-     * 根据用户id和结算月查询结算记录
-     * @param userId 用户ID
-     * @param settleMonth 结算月
-     * @return
-     */
-    List<SettlePointsHistory> querySettlePointsHistory(Long userId, String settleMonth);
-}

+ 14 - 0
src/main/java/com/punchsettle/server/atomic/service/ISettleTaskHistoryService.java

@@ -1,5 +1,7 @@
 package com.punchsettle.server.atomic.service;
 
+import com.punchsettle.server.atomic.entity.SettleTaskHistory;
+
 /**
  * @author tyuio
  * @version 1.0.0
@@ -7,4 +9,16 @@ package com.punchsettle.server.atomic.service;
  * @description 结算任务执行记录表 service
  */
 public interface ISettleTaskHistoryService {
+
+    /**
+     * 新增
+     * @param settleTaskHistory
+     */
+    void insert(SettleTaskHistory settleTaskHistory);
+
+    /**
+     * 更新
+     * @param settleTaskHistory
+     */
+    void update(SettleTaskHistory settleTaskHistory);
 }

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

@@ -0,0 +1,20 @@
+package com.punchsettle.server.atomic.service;
+
+import com.punchsettle.server.atomic.entity.SettleTaskRelaHistory;
+
+import java.util.List;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @date 2025/5/6 18:04
+ * @description 结算任务关联记录 service
+ */
+public interface ISettleTaskRelaHistoryService {
+
+    /**
+     * 批量新增
+     * @param settleTaskRelaHistories
+     */
+    void insertList(List<SettleTaskRelaHistory> settleTaskRelaHistories);
+}

+ 28 - 0
src/main/java/com/punchsettle/server/atomic/service/ISettleUserHistoryService.java

@@ -0,0 +1,28 @@
+package com.punchsettle.server.atomic.service;
+
+import com.punchsettle.server.atomic.entity.SettleUserHistory;
+import com.punchsettle.server.pojo.settle.SettleUserHistoryQuery;
+
+import java.util.List;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @date 2025/4/8 10:38
+ * @description 结算用户记录表 service
+ */
+public interface ISettleUserHistoryService {
+
+    /**
+     * 批量新增
+     * @param settlePointsHistories
+     */
+    void insertList(List<SettleUserHistory> settlePointsHistories);
+
+    /**
+     * 按条件查询查询结算用户记录
+     * @param query
+     * @return
+     */
+    List<SettleUserHistory> querySettleUserHistory(SettleUserHistoryQuery query);
+}

+ 5 - 4
src/main/java/com/punchsettle/server/atomic/service/IUserService.java

@@ -1,5 +1,6 @@
 package com.punchsettle.server.atomic.service;
 
+import java.util.Collection;
 import java.util.List;
 
 import com.punchsettle.server.atomic.entity.User;
@@ -33,10 +34,10 @@ public interface IUserService {
     void insert(User user);
 
     /**
-     * 查询所有用户
+     * 查询所有用户ID
      * @return
      */
-    List<User> list();
+    List<Long> listId();
 
     /**
      * 根据ID更新
@@ -49,11 +50,11 @@ public interface IUserService {
      * @param ids
      * @return
      */
-    List<User> listByIds(List<Long> ids);
+    List<User> listByIds(Collection<Long> ids);
 
     /**
      * 批量更新用户信息
      * @param users
      */
-    void batchUpdateUser(List<User> users);
+    void batchUpdate(List<User> users);
 }

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

@@ -25,7 +25,7 @@ public class AccountTransferHistoryServiceImpl implements IAccountTransferHistor
     private AccountTransferHistoryMapper accountTransferHistoryMapper;
 
     @Override
-    public void batchInsert(List<AccountTransferHistory> accountTransferHistories) {
+    public void insertList(List<AccountTransferHistory> accountTransferHistories) {
         Assert.isNull(accountTransferHistories);
         accountTransferHistoryMapper.insertList(accountTransferHistories);
     }

+ 0 - 44
src/main/java/com/punchsettle/server/atomic/service/impl/SettlePointsHistoryServiceImpl.java

@@ -1,44 +0,0 @@
-package com.punchsettle.server.atomic.service.impl;
-
-import com.punchsettle.server.atomic.entity.AccountTransferHistory;
-import com.punchsettle.server.atomic.entity.SettlePointsHistory;
-import com.punchsettle.server.atomic.mapper.SettlePointsHistoryMapper;
-import com.punchsettle.server.atomic.service.ISettlePointsHistoryService;
-import com.punchsettle.server.common.utils.Assert;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import tk.mybatis.mapper.weekend.Weekend;
-import tk.mybatis.mapper.weekend.WeekendCriteria;
-
-import java.util.List;
-
-/**
- * @author tyuio
- * @version 1.0.0
- * @date 2025/4/8 10:55
- * @description 结算积分记录表 service
- */
-@Service
-public class SettlePointsHistoryServiceImpl implements ISettlePointsHistoryService {
-
-    @Autowired
-    private SettlePointsHistoryMapper settlePointsHistoryMapper;
-
-    @Override
-    public void insertList(List<SettlePointsHistory> settlePointsHistories) {
-        Assert.notEmpty(settlePointsHistories);
-        settlePointsHistoryMapper.insertList(settlePointsHistories);
-    }
-
-    @Override
-    public List<SettlePointsHistory> querySettlePointsHistory(Long userId, String settleMonth) {
-        Assert.isNull(userId);
-        Assert.isNull(settleMonth);
-
-        Weekend<SettlePointsHistory> weekend = Weekend.of(SettlePointsHistory.class);
-        WeekendCriteria<SettlePointsHistory, Object> criteria = weekend.weekendCriteria();
-        criteria.andEqualTo(SettlePointsHistory::getUserId, userId);
-        criteria.andLike(SettlePointsHistory::getSettleDate, String.format("%s%%", settleMonth));
-        return settlePointsHistoryMapper.selectByExample(weekend);
-    }
-}

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

@@ -1,6 +1,10 @@
 package com.punchsettle.server.atomic.service.impl;
 
+import com.punchsettle.server.atomic.entity.SettleTaskHistory;
+import com.punchsettle.server.atomic.mapper.SettleTaskHistoryMapper;
 import com.punchsettle.server.atomic.service.ISettleTaskHistoryService;
+import com.punchsettle.server.common.utils.Assert;
+import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 /**
@@ -11,4 +15,19 @@ import org.springframework.stereotype.Service;
  */
 @Service
 public class SettleTaskHistoryServiceImpl implements ISettleTaskHistoryService {
+
+    @Autowired
+    private SettleTaskHistoryMapper settleTaskHistoryMapper;
+
+    @Override
+    public void insert(SettleTaskHistory settleTaskHistory) {
+        Assert.isNull(settleTaskHistory);
+        settleTaskHistoryMapper.insertSelective(settleTaskHistory);
+    }
+
+    @Override
+    public void update(SettleTaskHistory settleTaskHistory) {
+        Assert.isNull(settleTaskHistory);
+        settleTaskHistoryMapper.updateByPrimaryKeySelective(settleTaskHistory);
+    }
 }

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

@@ -0,0 +1,52 @@
+package com.punchsettle.server.atomic.service.impl;
+
+import com.punchsettle.server.atomic.entity.SettleUserHistory;
+import com.punchsettle.server.atomic.mapper.SettleUserHistoryMapper;
+import com.punchsettle.server.atomic.service.ISettleUserHistoryService;
+import com.punchsettle.server.common.utils.Assert;
+import com.punchsettle.server.pojo.settle.SettleUserHistoryQuery;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.StringUtils;
+import tk.mybatis.mapper.weekend.Weekend;
+import tk.mybatis.mapper.weekend.WeekendCriteria;
+
+import java.util.List;
+import java.util.Objects;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @date 2025/4/8 10:55
+ * @description 结算用户记录表 service
+ */
+@Service
+public class SettleUserHistoryServiceImpl implements ISettleUserHistoryService {
+
+    @Autowired
+    private SettleUserHistoryMapper settleUserHistoryMapper;
+
+    @Override
+    public void insertList(List<SettleUserHistory> settlePointsHistories) {
+        Assert.notEmpty(settlePointsHistories);
+        settleUserHistoryMapper.insertList(settlePointsHistories);
+    }
+
+    @Override
+    public List<SettleUserHistory> querySettleUserHistory(SettleUserHistoryQuery query) {
+        Assert.isNull(query);
+
+        Weekend<SettleUserHistory> weekend = Weekend.of(SettleUserHistory.class);
+        WeekendCriteria<SettleUserHistory, Object> criteria = weekend.weekendCriteria();
+        if (Objects.nonNull(query.getUserId())) {
+            criteria.andEqualTo(SettleUserHistory::getUserId, query.getUserId());
+        }
+        if (StringUtils.hasText(query.getSettleDate())) {
+            criteria.andEqualTo(SettleUserHistory::getSettleDate, query.getSettleDate());
+        }
+        if (StringUtils.hasText(query.getSettleDateLike())) {
+            criteria.andLike(SettleUserHistory::getSettleDate, String.format("%s%%", query.getSettleDateLike()));
+        }
+        return settleUserHistoryMapper.selectByExample(weekend);
+    }
+}

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

@@ -2,6 +2,7 @@ package com.punchsettle.server.atomic.service.impl;
 
 import java.util.List;
 
+import com.punchsettle.server.atomic.entity.StatPoints;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.util.StringUtils;
@@ -34,8 +35,11 @@ public class StatNewUserServiceImpl implements IStatNewUserService {
 
         Weekend<StatNewUser> weekend = WeekendUtils.createExcludeAuditFields(StatNewUser.class);
         WeekendCriteria<StatNewUser, Object> criteria = weekend.weekendCriteria();
-        if (StringUtils.hasText(query.getStatStartTime()) && StringUtils.hasText(query.getStatEndTime())) {
-            criteria.andBetween(StatNewUser::getStatTime, query.getStatStartTime(), query.getStatEndTime());
+        if (StringUtils.hasText(query.getStatStartTime())) {
+            criteria.andGreaterThanOrEqualTo(StatNewUser::getStatTime, query.getStatStartTime());
+        }
+        if (StringUtils.hasText(query.getStatEndTime())) {
+            criteria.andLessThanOrEqualTo(StatNewUser::getStatTime, query.getStatEndTime());
         }
         return statNewUserMapper.selectByExample(weekend);
     }

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

@@ -36,8 +36,11 @@ public class StatPointsServiceImpl implements IStatPointsService {
         if (Objects.nonNull(query.getUserId())) {
             criteria.andEqualTo(StatPoints::getUserId, query.getUserId());
         }
-        if (StringUtils.hasText(query.getStatStartTime()) && StringUtils.hasText(query.getStatEndTime())) {
-            criteria.andBetween(StatPoints::getStatTime, query.getStatStartTime(), query.getStatEndTime());
+        if (StringUtils.hasText(query.getStatStartTime())) {
+            criteria.andGreaterThanOrEqualTo(StatPoints::getStatTime, query.getStatStartTime());
+        }
+        if (StringUtils.hasText(query.getStatEndTime())) {
+            criteria.andLessThanOrEqualTo(StatPoints::getStatTime, query.getStatEndTime());
         }
         return statPointsMapper.selectByExample(weekend);
     }

+ 12 - 4
src/main/java/com/punchsettle/server/atomic/service/impl/UserServiceImpl.java

@@ -1,7 +1,9 @@
 package com.punchsettle.server.atomic.service.impl;
 
+import java.util.Collection;
 import java.util.List;
 import java.util.Objects;
+import java.util.stream.Collectors;
 
 import com.punchsettle.server.utiis.WeekendUtils;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -55,8 +57,14 @@ public class UserServiceImpl implements IUserService {
     }
 
     @Override
-    public List<User> list() {
-        return userMapper.selectAll();
+    public List<Long> listId() {
+        Weekend<User> weekend = Weekend.of(User.class);
+        weekend.selectProperties(User::getId);
+        List<User> users = userMapper.selectByExample(weekend);
+        if (CollectionUtils.isEmpty(users)) {
+            return List.of();
+        }
+        return users.stream().map(User::getId).collect(Collectors.toList());
     }
 
     @Override
@@ -66,7 +74,7 @@ public class UserServiceImpl implements IUserService {
     }
 
     @Override
-    public List<User> listByIds(List<Long> ids) {
+    public List<User> listByIds(Collection<Long> ids) {
         if(CollectionUtils.isEmpty(ids)) {
             return List.of();
         }
@@ -78,7 +86,7 @@ public class UserServiceImpl implements IUserService {
     }
 
     @Override
-    public void batchUpdateUser(List<User> users) {
+    public void batchUpdate(List<User> users) {
         Assert.notEmpty(users);
         userMapper.batchUpdateSelective(users);
     }

+ 23 - 0
src/main/java/com/punchsettle/server/constant/PointsDistributeStatusEnum.java

@@ -0,0 +1,23 @@
+package com.punchsettle.server.constant;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @date 2025/5/6 20:01
+ * @description 积分下发状态枚举(已分发-DISTRIBUTE,未分发-NOT_DISTRIBUTE)
+ */
+@Getter
+@AllArgsConstructor
+public enum PointsDistributeStatusEnum {
+
+    DISTRIBUTE("已分发"),
+    NOT_DISTRIBUTE("未分发");
+
+    /**
+     * 名称
+     */
+    private String name;
+}

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

@@ -7,14 +7,15 @@ import lombok.Getter;
  * @author tyuio
  * @version 1.0.0
  * @date 2025/4/17 22:26
- * @description 结算结果枚举(未结算-UNSETTLED,已结算-SETTLED)
+ * @description 结算结果(已结算-SETTLED,撤销结算-REVOKE_SETTLED,无需结算-NOT_SETTLED)
  */
 @Getter
 @AllArgsConstructor
 public enum SettleResultEnum {
 
-    UNSETTLED("未结算"),
-    SETTLED("已结算");
+    SETTLE("已结算"),
+    REVOKE_SETTLED("撤销结算"),
+    NOT_SETTLED("无需结算");
 
     /**
      * 名称

+ 2 - 1
src/main/java/com/punchsettle/server/pojo/account/AccountQuery.java

@@ -3,6 +3,7 @@ package com.punchsettle.server.pojo.account;
 import com.punchsettle.server.constant.AccountCategoryEnum;
 import lombok.Data;
 
+import java.util.Collection;
 import java.util.List;
 
 /**
@@ -17,7 +18,7 @@ public class AccountQuery {
     /**
      * 用户id列表
      */
-    private List<Long> userIds;
+    private Collection<Long> userIds;
 
     /**
      * 账户类型

+ 57 - 0
src/main/java/com/punchsettle/server/pojo/settle/SettleData.java

@@ -0,0 +1,57 @@
+package com.punchsettle.server.pojo.settle;
+
+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.PiStatus;
+import com.punchsettle.server.atomic.entity.PiTaskHistory;
+import com.punchsettle.server.pojo.punchIn.PiTaskData;
+
+import lombok.Data;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @date 2025/4/16 10:17
+ * @description 结算数据
+ */
+@Data
+public class SettleData {
+
+    /**
+     * 用户ID
+     */
+    private Long userId;
+
+    /**
+     * 打卡多任务
+     */
+    private PiMultiTask piMultiTask;
+
+    /**
+     * 打卡多任务拓展信息
+     */
+    private List<PiMultiTaskExt> piMultiTaskExtList;
+
+    /**
+     * 多任务打卡记录
+     */
+    private PiMultiTaskHistory piMultiTaskHistory;
+
+    /**
+     * 打卡多任务关联的打卡记录
+     */
+    private List<PiTaskHistory> relaPunchInTaskHistories;
+
+    /**
+     * 打卡多任务状态
+     */
+    private PiStatus piStatus;
+
+    /**
+     * 打卡任务列表
+     */
+    private List<PiTaskData> piTaskDataList;
+}

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

@@ -0,0 +1,28 @@
+package com.punchsettle.server.pojo.settle;
+
+import lombok.Data;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @date 2025/5/6 19:35
+ * @description 结算用户记录 查询类
+ */
+@Data
+public class SettleUserHistoryQuery {
+
+    /**
+     * 用户ID
+     */
+    private Long userId;
+
+    /**
+     * 结算日期(右模糊)
+     */
+    private String settleDateLike;
+
+    /**
+     * 结算日期
+     */
+    private String settleDate;
+}

+ 8 - 0
src/main/java/com/punchsettle/server/service/manager/ISettleManager.java

@@ -19,4 +19,12 @@ public interface ISettleManager {
      * @return
      */
     List<SettlePointsHistoryVO> querySettlePointsHistory(Long userId, String settleMonth);
+
+    /**
+     * 结算
+     * @param userIds 用户列表
+     * @param punchInDateStr 打卡日期
+     * @param settleTaskHistoryId 结算任务ID
+     */
+    void settle(List<Long> userIds, String punchInDateStr, Long settleTaskHistoryId);
 }

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

@@ -198,7 +198,7 @@ public class AccountManagerImpl implements IAccountManager {
         accountTransferHistory.setSaPointsAfterTransfer(afterSenderAccountPoints);
         accountTransferHistory.setRaPointsBeforeTransfer(beforeRecipientAccountPoints);
         accountTransferHistory.setRaPointsAfterTransfer(afterRecipientAccountPoints);
-        accountTransferHistoryService.batchInsert(Arrays.asList(accountTransferHistory));
+        accountTransferHistoryService.insertList(Arrays.asList(accountTransferHistory));
 
         // 转出账户和转入账户 更新
         Account updateSenderAccount = new Account();

+ 33 - 12
src/main/java/com/punchsettle/server/service/manager/impl/PunchInManagerImpl.java

@@ -144,10 +144,6 @@ public class PunchInManagerImpl implements IPunchInManager {
                     // 获取并设置已打卡记录
                     PiTaskHistory piTaskHistory = piTaskHistoryMap.get(piTask.getUniqueId());
                     if (Objects.nonNull(piTaskHistory)) {
-                        // 判断当前的打卡结果
-                        PunchInResultEnum punchInResult = punchInCoreManager.judgePunchInResultInTask(piTask, piTaskHistory);
-
-                        piTaskToDoVO.setPunchInResult(punchInResult);
                         piTaskToDoVO.setCurrentCountTrack(piTaskHistory.getCountTrack());
                         piTaskToDoVO.setCurrentTimeTrack(piTaskHistory.getTimeTrack());
                     }
@@ -263,9 +259,7 @@ public class PunchInManagerImpl implements IPunchInManager {
             if (Objects.isNull(piTaskHistory)) {
                 return PunchInResultViewEnum.TODAY_UNKNOWN;
             }
-            // 今天有打卡记录,完成打卡则显示完成,未完成则显示未知
-            PunchInResultEnum punchInResult = punchInCoreManager.judgePunchInResultInTask(piTask, piTaskHistory);
-            return PunchInResultEnum.DONE.equals(punchInResult) ? PunchInResultViewEnum.DONE : PunchInResultViewEnum.TODAY_UNKNOWN;
+            return PunchInResultEnum.DONE.equals(piTaskHistory.getPunchInResult()) ? PunchInResultViewEnum.DONE : PunchInResultViewEnum.TODAY_UNKNOWN;
         }
 
         // 不符合任何情况则是无需打卡
@@ -283,6 +277,7 @@ public class PunchInManagerImpl implements IPunchInManager {
     }
 
     @Override
+    @Transactional(rollbackFor = Exception.class)
     public void saveTask(PiTaskRequest request) {
         Assert.isNullInBusiness(request, "请传入任务信息");
 
@@ -358,10 +353,35 @@ public class PunchInManagerImpl implements IPunchInManager {
             piTaskService.update(updatePiTask);
         }
 
-        // 清楚缓存
+        // 今天
+        String today = LocalDate.now().toString();
+
+        // 不是新增打卡任务 更新打卡记录
+        if (Objects.nonNull(addPiTask.getUniqueId())) {
+            // 查询今天的打卡记录
+            PiTaskHistory oldPiTaskHistory = piTaskHistoryService.getByTaskUniqueIdAndPunchInDate(addPiTask.getUniqueId(), today);
+            // 已打卡则重新判断打卡状态
+            if (Objects.nonNull(oldPiTaskHistory)) {
+                // 新编辑的打卡任务+旧的打卡记录判断打卡结果
+                PunchInResultEnum punchInResult = punchInCoreManager.judgePunchInResultInTask(addPiTask, oldPiTaskHistory);
+
+                // 更新
+                PiTaskHistory updatePiTaskHistory = new PiTaskHistory();
+                updatePiTaskHistory.setId(oldPiTaskHistory.getId());
+                updatePiTaskHistory.setPunchInResult(punchInResult);
+                piTaskHistoryService.update(updatePiTaskHistory);
+            }
+        }
+
+
+        // 清除缓存
         Long currentUserId = UserUtils.getCurrentUserId();
         cacheManager.getCache(CacheNameConstant.TASK_LIST_FOR_USER).evict(currentUserId);
         cacheManager.getCache(CacheNameConstant.TASK_LIST_VO).evict(currentUserId);
+        cacheManager.getCache(CacheNameConstant.TASK_PUNCH_IN_HISTORY).evict(String.format("%s_%s", currentUserId, today));
+        cacheManager.getCache(CacheNameConstant.TASK_HISTORY_LIST_FOR_USER).evict(String.format("%s_%s", currentUserId, today));
+        cacheManager.getCache(CacheNameConstant.TASK_STAT).evict(String.format("%s_%s", currentUserId, today.substring(0, 7)));
+        cacheManager.getCache(CacheNameConstant.TASK_STAT).evict(String.format("%s_%s", currentUserId, today.substring(0, 4)));
     }
 
     @Override
@@ -404,13 +424,12 @@ public class PunchInManagerImpl implements IPunchInManager {
 
         // 待更新/新增的打卡记录
         PiTaskHistory tempPiTaskHistory = new PiTaskHistory();
-        tempPiTaskHistory.setSettlePiTaskId(piTask.getId());
+        tempPiTaskHistory.setTaskId(piTask.getId());
         // 不存在则新增,存在则更新
         if (Objects.isNull(oldPiTaskHistory)) {
             tempPiTaskHistory.setTaskUniqueId(piTask.getUniqueId());
             tempPiTaskHistory.setPunchInDate(punchInDate);
             tempPiTaskHistory.setUserId(currentUserId);
-            tempPiTaskHistory.setSettleResult(SettleResultEnum.UNSETTLED);
         } else {
             tempPiTaskHistory.setId(oldPiTaskHistory.getId());
         }
@@ -455,6 +474,7 @@ public class PunchInManagerImpl implements IPunchInManager {
         cacheManager.getCache(CacheNameConstant.TASK_PUNCH_IN_HISTORY).evict(String.format("%s_%s", currentUserId, punchInDate));
         cacheManager.getCache(CacheNameConstant.TASK_HISTORY_LIST_FOR_USER).evict(String.format("%s_%s", currentUserId, punchInDate));
         cacheManager.getCache(CacheNameConstant.TASK_STAT).evict(String.format("%s_%s", currentUserId, punchInDate.substring(0, 7)));
+        cacheManager.getCache(CacheNameConstant.TASK_STAT).evict(String.format("%s_%s", currentUserId, punchInDate.substring(0, 4)));
     }
 
     @Override
@@ -486,7 +506,7 @@ public class PunchInManagerImpl implements IPunchInManager {
 
         PiTaskHistory updatePiTaskHistory = new PiTaskHistory();
         updatePiTaskHistory.setId(piTaskHistory.getId());
-        updatePiTaskHistory.setSettlePiTaskId(piTask.getId());
+        updatePiTaskHistory.setTaskId(piTask.getId());
 
         // 单次打卡,次数置为0
         if (PunchInMethodEnum.SINGLE.equals(piTask.getPunchInMethod())) {
@@ -521,6 +541,7 @@ public class PunchInManagerImpl implements IPunchInManager {
         cacheManager.getCache(CacheNameConstant.TASK_PUNCH_IN_HISTORY).evict(String.format("%s_%s", currentUserId, punchInDate));
         cacheManager.getCache(CacheNameConstant.TASK_HISTORY_LIST_FOR_USER).evict(String.format("%s_%s", currentUserId, punchInDate));
         cacheManager.getCache(CacheNameConstant.TASK_STAT).evict(String.format("%s_%s", currentUserId, punchInDate.substring(0, 7)));
+        cacheManager.getCache(CacheNameConstant.TASK_STAT).evict(String.format("%s_%s", currentUserId, punchInDate.substring(0, 4)));
     }
 
     @Override
@@ -556,7 +577,7 @@ public class PunchInManagerImpl implements IPunchInManager {
         List<PiTaskHistory> piTaskHistories = piTaskHistoryService.queryByCondition(piTaskHistoryQuery);
 
         // 查询打卡任务
-        Set<Long> piTaskIds = piTaskHistories.stream().map(PiTaskHistory::getSettlePiTaskId).collect(Collectors.toSet());
+        Set<Long> piTaskIds = piTaskHistories.stream().map(PiTaskHistory::getTaskId).collect(Collectors.toSet());
         PiTaskQuery piTaskQuery = new PiTaskQuery();
         piTaskQuery.setIds(piTaskIds);
         List<PiTask> piTasks = piTaskService.queryByCondition(piTaskQuery);

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

@@ -37,7 +37,7 @@ 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.SettlePointsHistory;
 import com.punchsettle.server.atomic.entity.StatPiTaskMonth;
 import com.punchsettle.server.atomic.entity.StatPiTaskWeek;
 import com.punchsettle.server.atomic.entity.User;
@@ -50,7 +50,7 @@ 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.ISettlePointsHistoryService;
+//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.IUserService;
@@ -135,8 +135,8 @@ public class PunchInSettleManagerImpl implements IPunchInSettleManager {
     @Autowired
     private IUserService userService;
 
-    @Autowired
-    private ISettlePointsHistoryService settlePointsHistoryService;
+//    @Autowired
+//    private ISettlePointsHistoryService settlePointsHistoryService;
 
     @Autowired
     private IPunchInCoreManager punchInManager;
@@ -175,7 +175,7 @@ public class PunchInSettleManagerImpl implements IPunchInSettleManager {
         // 打卡任务月统计 新增列表
         List<StatPiTaskMonth> addStatPiTaskMonthList = new ArrayList<>();
         // 结算积分记录 新增列表
-        List<SettlePointsHistory> addSettlePointsHistories = new ArrayList<>();
+//        List<SettlePointsHistory> addSettlePointsHistories = new ArrayList<>();
         // 转张记录 新增列表
         List<AccountTransferHistory> addAccountTransferHistories = new ArrayList<>();
         // 账户 更新列表
@@ -218,12 +218,12 @@ public class PunchInSettleManagerImpl implements IPunchInSettleManager {
                 updatePiTaskHistory.setId(piTaskHistory.getId());
 
                 // 记录当前状态数据
-                updatePiTaskHistory.setTaskContinueStatus(piStatus.getTaskContinueStatus());
-                updatePiTaskHistory.setTaskContinueDay(piStatus.getTaskContinueDay());
-                updatePiTaskHistory.setContinueStage(piStatus.getContinueStage());
-                updatePiTaskHistory.setStageStartDate(piStatus.getStageStartDate());
-                updatePiTaskHistory.setStageEndDate(piStatus.getStageEndDate());
-                updatePiTaskHistory.setContinueInterruptedCount(piStatus.getContinueInterruptedCount());
+//                updatePiTaskHistory.setTaskContinueStatus(piStatus.getTaskContinueStatus());
+//                updatePiTaskHistory.setTaskContinueDay(piStatus.getTaskContinueDay());
+//                updatePiTaskHistory.setContinueStage(piStatus.getContinueStage());
+//                updatePiTaskHistory.setStageStartDate(piStatus.getStageStartDate());
+//                updatePiTaskHistory.setStageEndDate(piStatus.getStageEndDate());
+//                updatePiTaskHistory.setContinueInterruptedCount(piStatus.getContinueInterruptedCount());
 
                 // 判断打卡结果
                 PunchInResultEnum punchInResult = punchInManager.judgePunchInResultInTask(piTask, piTaskHistory);
@@ -243,10 +243,10 @@ public class PunchInSettleManagerImpl implements IPunchInSettleManager {
                 piStatus.setPointsInMonth(piStatus.getPointsInMonth() + taskPoints);
 
                 // 打卡记录 更新
-                updatePiTaskHistory.setSettlePoints(taskPoints);
-                updatePiTaskHistory.setSettleResult(SettleResultEnum.SETTLED);
-                updatePiTaskHistory.setSettlePiTaskId(piTask.getId());
-                updatePiTaskHistory.setSettleTaskHistoryId(settleTaskHistoryId);
+//                updatePiTaskHistory.setSettlePoints(taskPoints);
+//                updatePiTaskHistory.setSettleResult(SettleResultEnum.SETTLED);
+//                updatePiTaskHistory.setSettlePiTaskId(piTask.getId());
+//                updatePiTaskHistory.setSettleTaskHistoryId(settleTaskHistoryId);
 
                 updatePiStatusList.add(piStatus);
                 updatePunchInTaskHistories.add(updatePiTaskHistory);
@@ -300,7 +300,7 @@ public class PunchInSettleManagerImpl implements IPunchInSettleManager {
 
             // 设置打卡记录表信息
             updatePiMultiTaskHistory.setSettlePoints(multiTaskPoints);
-            updatePiMultiTaskHistory.setSettleResult(SettleResultEnum.SETTLED);
+//            updatePiMultiTaskHistory.setSettleResult(SettleResultEnum.SETTLED);
             updatePiMultiTaskHistory.setSettleTaskHistoryId(settleTaskHistoryId);
             updatePunchInMultiTaskHistories.add(updatePiMultiTaskHistory);
 
@@ -330,23 +330,23 @@ public class PunchInSettleManagerImpl implements IPunchInSettleManager {
             addAccountTransferHistories.add(accountTransferHistory);
 
             // 设置结算积分记录
-            SettlePointsHistory addSettlePointsHistory = new SettlePointsHistory();
-            addSettlePointsHistory.setSettleTaskHistoryId(settleTaskHistoryId);
-            addSettlePointsHistory.setUserId(user.getId());
-            addSettlePointsHistory.setSettleDate(punchInDateStr);
-            addSettlePointsHistory.setSettlePoints(settlePoints);
-            addSettlePointsHistory.setBeforeSettlePoints(beforeTotalPoints);
-            addSettlePointsHistory.setAfterSettlePoints(beforeTotalPoints + settlePoints);
-            addSettlePointsHistories.add(addSettlePointsHistory);
+//            SettlePointsHistory addSettlePointsHistory = new SettlePointsHistory();
+//            addSettlePointsHistory.setSettleTaskHistoryId(settleTaskHistoryId);
+//            addSettlePointsHistory.setUserId(user.getId());
+//            addSettlePointsHistory.setSettleDate(punchInDateStr);
+//            addSettlePointsHistory.setSettlePoints(settlePoints);
+//            addSettlePointsHistory.setBeforeSettlePoints(beforeTotalPoints);
+//            addSettlePointsHistory.setAfterSettlePoints(beforeTotalPoints + settlePoints);
+//            addSettlePointsHistories.add(addSettlePointsHistory);
         }
 
         // 数据入库
         if (!CollectionUtils.isEmpty(updateUserList)) {
-            userService.batchUpdateUser(updateUserList);
-        }
-        if (!CollectionUtils.isEmpty(addSettlePointsHistories)) {
-            settlePointsHistoryService.insertList(addSettlePointsHistories);
+            userService.batchUpdate(updateUserList);
         }
+//        if (!CollectionUtils.isEmpty(addSettlePointsHistories)) {
+////            settlePointsHistoryService.insertList(addSettlePointsHistories);
+//        }
         if (!CollectionUtils.isEmpty(addPiStatusHistories)) {
             piStatusHistoryService.insertList(addPiStatusHistories);
         }
@@ -369,7 +369,7 @@ public class PunchInSettleManagerImpl implements IPunchInSettleManager {
             accountService.batchUpdate(updateAccountList);
         }
         if (!CollectionUtils.isEmpty(addAccountTransferHistories)) {
-            accountTransferHistoryService.batchInsert(addAccountTransferHistories);
+            accountTransferHistoryService.insertList(addAccountTransferHistories);
         }
     }
 

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

@@ -1,21 +1,68 @@
 package com.punchsettle.server.service.manager.impl;
 
+import java.time.DayOfWeek;
+import java.time.LocalDate;
+import java.util.ArrayList;
+import java.util.HashMap;
 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.constant.CacheNameConstant;
+import com.punchsettle.server.pojo.settle.SettleUserHistoryQuery;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.cache.annotation.Cacheable;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.CollectionUtils;
 
-import com.punchsettle.server.atomic.entity.SettlePointsHistory;
-import com.punchsettle.server.atomic.service.ISettlePointsHistoryService;
+import com.punchsettle.server.atomic.ContinueTask;
+import com.punchsettle.server.atomic.entity.PiMultiTask;
+import com.punchsettle.server.atomic.entity.PiMultiTaskExt;
+import com.punchsettle.server.atomic.entity.PiMultiTaskHistory;
+import com.punchsettle.server.atomic.entity.PiMultiTaskRela;
+import com.punchsettle.server.atomic.entity.PiStatus;
+import com.punchsettle.server.atomic.entity.PiTask;
+import com.punchsettle.server.atomic.entity.PiTaskExt;
+import com.punchsettle.server.atomic.entity.PiTaskHistory;
+import com.punchsettle.server.atomic.entity.SettleTaskRelaHistory;
+import com.punchsettle.server.atomic.entity.SettleUserHistory;
+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.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.ISettleUserHistoryService;
+import com.punchsettle.server.atomic.service.ISettleTaskRelaHistoryService;
 import com.punchsettle.server.common.utils.Assert;
+import com.punchsettle.server.constant.ArchiveStatusEnum;
+import com.punchsettle.server.constant.CacheNameConstant;
+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.constant.VersionStatusEnum;
+import com.punchsettle.server.pojo.punchIn.PiMultiTaskExtQuery;
+import com.punchsettle.server.pojo.punchIn.PiMultiTaskHistoryQuery;
+import com.punchsettle.server.pojo.punchIn.PiMultiTaskQuery;
+import com.punchsettle.server.pojo.punchIn.PiStatusQuery;
+import com.punchsettle.server.pojo.punchIn.PiTaskData;
+import com.punchsettle.server.pojo.punchIn.PiTaskExtQuery;
+import com.punchsettle.server.pojo.punchIn.PiTaskHistoryQuery;
+import com.punchsettle.server.pojo.punchIn.PiTaskQuery;
+import com.punchsettle.server.pojo.settle.SettleData;
 import com.punchsettle.server.pojo.settle.SettlePointsHistoryVO;
+import com.punchsettle.server.service.manager.IPunchInCoreManager;
+import com.punchsettle.server.service.manager.ISettleCoreManager;
 import com.punchsettle.server.service.manager.ISettleManager;
-import com.punchsettle.server.utiis.UserUtils;
+import com.punchsettle.server.utiis.DateUtils;
 
 import lombok.extern.slf4j.Slf4j;
 
@@ -30,7 +77,40 @@ import lombok.extern.slf4j.Slf4j;
 public class SettleManagerImpl implements ISettleManager {
 
     @Autowired
-    private ISettlePointsHistoryService settlePointsHistoryService;
+    private ISettleUserHistoryService settleUserHistoryService;
+
+    @Autowired
+    private IPiTaskService piTaskService;
+
+    @Autowired
+    private IPiTaskExtService piTaskExtService;
+
+    @Autowired
+    private IPiTaskHistoryService piTaskHistoryService;
+
+    @Autowired
+    private IPiStatusService piStatusService;
+
+    @Autowired
+    private IPiMultiTaskService piMultiTaskService;
+
+    @Autowired
+    private IPiMultiTaskExtService piMultiTaskExtService;
+
+    @Autowired
+    private IPiMultiTaskHistoryService piMultiTaskHistoryService;
+
+    @Autowired
+    private IPiMultiTaskRelaService piMultiTaskRelaService;
+
+    @Autowired
+    private IPunchInCoreManager punchInCoreManager;
+
+    @Autowired
+    private ISettleCoreManager settleCoreManager;
+
+    @Autowired
+    private ISettleTaskRelaHistoryService settleTaskRelaHistoryService;
 
     @Override
     @Cacheable(cacheNames = CacheNameConstant.SETTLE_POINTS_HISTORY, key = "#userId+'_'+settleMonth", condition = "#userId != null && settleMont != null && !settleMonth.isBlank()")
@@ -38,7 +118,10 @@ public class SettleManagerImpl implements ISettleManager {
         Assert.isNullInBusiness(settleMonth, "结算月份不能为空");
         Assert.isNullInBusiness(userId, "用户ID不能为空");
 
-        List<SettlePointsHistory> settlePointsHistories = settlePointsHistoryService.querySettlePointsHistory(userId, settleMonth);
+        SettleUserHistoryQuery settleUserHistoryQuery = new SettleUserHistoryQuery();
+        settleUserHistoryQuery.setUserId(userId);
+        settleUserHistoryQuery.setSettleDateLike(settleMonth);
+        List<SettleUserHistory> settlePointsHistories = settleUserHistoryService.querySettleUserHistory(settleUserHistoryQuery);
         if (CollectionUtils.isEmpty(settlePointsHistories)) {
             return List.of();
         }
@@ -49,4 +132,406 @@ public class SettleManagerImpl implements ISettleManager {
             return settlePointsHistoryVO;
         }).collect(Collectors.toList());
     }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void settle(List<Long> userIds, String punchInDateStr, Long settleTaskHistoryId) {
+        // 打卡日期
+        LocalDate punchInDate = LocalDate.parse(punchInDateStr);
+        // 是否周一
+        boolean isMonday = DayOfWeek.MONDAY.equals(punchInDate.getDayOfWeek());
+        // 是否打卡所在月第一天
+        boolean isFirstDayOfMonth = punchInDate.getDayOfMonth() == 1;
+        // 周期数
+        String yearWeek = DateUtils.getYearWeek(punchInDate);
+        // 月份数
+        String yearMonth = DateUtils.getYearMonth(punchInDate);
+
+        // 打卡状态 更新列表
+        List<PiStatus> addPiStatusList = new ArrayList<>();
+        // 新增结算用户记录
+        List<SettleUserHistory> addSettleUserHistories = new ArrayList<>();
+        // 用户ID-结算任务关联记录
+        Map<Long, List<SettleTaskRelaHistory>> settleTaskRelaHistoryMap = new HashMap<>();
+
+        // 获取结算数据
+        List<SettleData> settleDataList = getSettleData(userIds, punchInDateStr);
+
+        for (SettleData settleData : settleDataList) {
+            // 新增结算用户记录
+            SettleUserHistory addSettleUserHistory = new SettleUserHistory();
+            addSettleUserHistory.setUserId(settleData.getUserId());
+            addSettleUserHistory.setSettleDate(punchInDateStr);
+            addSettleUserHistory.setSettleTaskHistoryId(settleTaskHistoryId);
+            addSettleUserHistories.add(addSettleUserHistory);
+
+            // 不存在打卡任务则跳过
+            if (CollectionUtils.isEmpty(settleData.getPiTaskDataList())) {
+                addSettleUserHistory.setSettlePoints(0);
+                continue;
+            }
+
+            // 总结算积分
+            int totalSettlePoints = 0;
+
+            // 新增结算任务关联记录
+            List<SettleTaskRelaHistory> addSettleTaskRelaHistories = new ArrayList<>();
+            settleTaskRelaHistoryMap.put(settleData.getUserId(), addSettleTaskRelaHistories);
+
+            // 单任务处理
+            for (PiTaskData piTaskData : settleData.getPiTaskDataList()) {
+                // 打卡任务
+                PiTask piTask = piTaskData.getPiTask();
+
+                // 结算任务关联记录
+                SettleTaskRelaHistory addSettleTaskRelaHistory = new SettleTaskRelaHistory();
+                addSettleTaskRelaHistory.setSettleTaskHistoryId(settleTaskHistoryId);
+                addSettleTaskRelaHistory.setUserId(settleData.getUserId());
+                addSettleTaskRelaHistory.setSettleDate(punchInDateStr);
+                addSettleTaskRelaHistory.setPiTaskId(piTask.getId());
+                addSettleTaskRelaHistory.setPiTaskUniqueId(piTask.getUniqueId());
+
+                // 有打卡任务,但是今天无需结算
+                boolean repeatResult = punchInCoreManager.judgeRepeat(piTask, punchInDateStr);
+                if (!repeatResult) {
+                    addSettleTaskRelaHistory.setSettleResult(SettleResultEnum.NOT_SETTLED);
+                    addSettleTaskRelaHistory.setSettlePoints(0);
+                    addSettleTaskRelaHistories.add(addSettleTaskRelaHistory);
+                    continue;
+                }
+
+                // 打卡任务打卡记录
+                PiTaskHistory piTaskHistory = piTaskData.getPiTaskHistory();
+                // 打卡任务状态
+                PiStatus oldPiStatus = piTaskData.getPiStatus();
+                // 打卡任务拖扎信息
+                List<PiTaskExt> piTaskExtList = piTaskData.getPiTaskExtList();
+
+                // 复制昨天的打卡记录
+                PiStatus piStatus = new PiStatus();
+                BeanUtils.copyProperties(oldPiStatus, piStatus);
+                piStatus.setStatusDate(punchInDateStr);
+                addPiStatusList.add(piStatus);
+
+                // 更新打卡状态
+                refreshPiStatus(oldPiStatus, piTask, piTaskHistory, punchInDate, isMonday, isFirstDayOfMonth, yearWeek, yearMonth);
+
+                // 计算积分,要先刷新打卡状态
+                int settlePoints = settleCoreManager.calculatePointsInTask(piTask, piTaskExtList, piTaskHistory, oldPiStatus);
+
+                addSettleTaskRelaHistory.setSettleResult(SettleResultEnum.SETTLE);
+                addSettleTaskRelaHistory.setSettlePoints(settlePoints);
+                addSettleTaskRelaHistories.add(addSettleTaskRelaHistory);
+            }
+
+            // TODO 未处理多任务结算
+
+            // 设置总结算积分
+            addSettleUserHistory.setSettlePoints(totalSettlePoints);
+        }
+
+        // 数据入库
+        if (!CollectionUtils.isEmpty(addSettleUserHistories)) {
+            settleUserHistoryService.insertList(addSettleUserHistories);
+            // 处理关联数据
+            List<SettleTaskRelaHistory> addSettleTaskRelaHistories = addSettleUserHistories.stream().map(settleUserHistory -> {
+                        List<SettleTaskRelaHistory> settleTaskRelaHistories = settleTaskRelaHistoryMap.get(settleUserHistory.getUserId());
+                        if (!CollectionUtils.isEmpty(settleTaskRelaHistories)) {
+                            settleTaskRelaHistories.stream().forEach(v -> v.setSettleUserHistoryId(settleUserHistory.getId()));
+                        }
+                        return settleTaskRelaHistories;
+                    }).flatMap(List::stream) // 将每个List中的元素展平
+                    .collect(Collectors.toList());
+            if (!CollectionUtils.isEmpty(addSettleTaskRelaHistories)) {
+                settleTaskRelaHistoryService.insertList(addSettleTaskRelaHistories);
+            }
+        }
+        if (!CollectionUtils.isEmpty(addPiStatusList)) {
+            piStatusService.batchUpdate(addPiStatusList);
+        }
+    }
+
+    /**
+     * 获取用户ID-打卡结算数据关联
+     *
+     * @param userIds 设计的用户
+     * @param punchInDateStr 打卡日期
+     * @return
+     */
+    private List<SettleData> getSettleData(List<Long> userIds, String punchInDateStr) {
+
+        // 获取多任务信息,用户ID-多任务关联
+        PiMultiTaskQuery piMultiTaskQuery = new PiMultiTaskQuery();
+        piMultiTaskQuery.setMultiTaskTaskStatus(VersionStatusEnum.ACTIVE);
+        piMultiTaskQuery.setUserIds(userIds);
+        List<PiMultiTask> piMultiTasks = piMultiTaskService.queryByCondition(piMultiTaskQuery);
+        Map<Long, PiMultiTask> piMultiTaskMap = piMultiTasks.stream()
+                .collect(Collectors.toMap(PiMultiTask::getUserId, Function.identity(), (key1, key2) -> key1));
+
+        // 多任务ID
+        Set<Long> multiTaskIds = piMultiTasks.stream().map(PiMultiTask::getId).collect(Collectors.toSet());
+        // 多任务唯一ID
+        Set<Long> multiTaskUniqueIds = piMultiTasks.stream().map(PiMultiTask::getUniqueId).collect(Collectors.toSet());
+
+        // 获取多任务拓展信息,多任务ID-多任务拓展关联
+        PiMultiTaskExtQuery piMultiTaskExtQuery = new PiMultiTaskExtQuery();
+        piMultiTaskExtQuery.setMultiTaskIds(multiTaskIds);
+        List<PiMultiTaskExt> piMultiTaskExtList = piMultiTaskExtService.queryByCondition(piMultiTaskExtQuery);
+        Map<Long, List<PiMultiTaskExt>> piMultiTaskExtMap =
+                piMultiTaskExtList.stream().collect(Collectors.groupingBy(PiMultiTaskExt::getMultiTaskId));
+
+        // 获取多任务打卡历史信息,多任务唯一ID-多任务打卡历史关联
+        PiMultiTaskHistoryQuery piMultiTaskHistoryQuery = new PiMultiTaskHistoryQuery();
+        piMultiTaskHistoryQuery.setPunchInMultiTaskUniqueIds(multiTaskUniqueIds);
+        piMultiTaskHistoryQuery.setPunchInDate(punchInDateStr);
+        List<PiMultiTaskHistory> piMultiTaskHistories =
+                piMultiTaskHistoryService.queryByCondition(piMultiTaskHistoryQuery);
+        Map<Long, PiMultiTaskHistory> piMultiTaskHistoryMap = piMultiTaskHistories.stream().collect(
+                Collectors.toMap(PiMultiTaskHistory::getMultiTaskUniqueId, Function.identity(), (key1, key2) -> key1));
+
+        // 打卡任务状态
+        PiStatusQuery piStatusQuery = new PiStatusQuery();
+        piStatusQuery.setUserIds(userIds);
+        List<PiStatus> piStatusList = piStatusService.queryByCondition(piStatusQuery);
+        // 打卡任务状态,多任务唯一ID-打卡状态关联
+        Map<Long, PiStatus> piStatusMapInMultiTask = piStatusList.stream().filter(v -> Objects.nonNull(v.getMultiTaskUniqueId())).collect(Collectors.toMap(PiStatus::getMultiTaskUniqueId, Function.identity(), (key1, key2) -> key1));
+        // 打卡任务状态,任务唯一ID-打卡状态关联
+        Map<Long, PiStatus> piStatusMapInTask = piStatusList.stream().filter(v -> Objects.nonNull(v.getTaskUniqueId())).collect(Collectors.toMap(PiStatus::getTaskUniqueId, Function.identity(), (key1, key2) -> key1));
+
+        // 多任务关联打卡任务,多任务ID-多任务关联打卡任务关联
+        List<PiMultiTaskRela> piMultiTaskRelaList = piMultiTaskRelaService.queryByMultiTaskId(multiTaskIds);
+        Map<Long, List<PiMultiTaskRela>> piMultiTaskRelaMap =
+                piMultiTaskRelaList.stream().collect(Collectors.groupingBy(PiMultiTaskRela::getMultiTaskId));
+
+        // 获取打卡任务信息,打卡任务唯一ID-打卡任务关联
+        PiTaskQuery piTaskQuery = new PiTaskQuery();
+        piTaskQuery.setTaskStatus(VersionStatusEnum.ACTIVE);
+        piTaskQuery.setArchiveStatus(ArchiveStatusEnum.ACTIVE);
+        piTaskQuery.setUserIds(userIds);
+        List<PiTask> piTasks = piTaskService.queryByCondition(piTaskQuery);
+        Map<Long, List<PiTask>> piTaskMap =
+                piTasks.stream().collect(Collectors.groupingBy(PiTask::getCreatedBy));
+
+        // 获取打卡记录,任务唯一 ID-打卡记录关联
+        PiTaskHistoryQuery piTaskHistoryQuery = new PiTaskHistoryQuery();
+        piTaskHistoryQuery.setPunchInDate(punchInDateStr);
+        piTaskHistoryQuery.setUserIds(userIds);
+        List<PiTaskHistory> punchInTaskHistories = piTaskHistoryService.queryByCondition(piTaskHistoryQuery);
+        Map<Long, PiTaskHistory> piTaskHistoryMap =
+                punchInTaskHistories.stream().collect(Collectors.toMap(PiTaskHistory::getTaskUniqueId, Function.identity(), (key1, key2) -> key1));
+
+        // 打卡任务ID
+        Set<Long> punchInTaskIds = piTasks.stream().map(PiTask::getId).collect(Collectors.toSet());
+
+        // 获取打卡任务拓展表,打卡任务ID-打卡任务拓展关联
+        PiTaskExtQuery piTaskExtQuery = new PiTaskExtQuery();
+        piTaskExtQuery.setPunchInTaskIds(punchInTaskIds);
+        List<PiTaskExt> piTaskExtList = piTaskExtService.queryByCondition(piTaskExtQuery);
+        Map<Long, List<PiTaskExt>> piTaskExtGroupList =
+                piTaskExtList.stream().collect(Collectors.groupingBy(PiTaskExt::getTaskId));
+
+        return userIds.stream().map(userId -> {
+            SettleData settleData = new SettleData();
+
+            // 设置用户ID
+            settleData.setUserId(userId);
+
+            // TODO 获取并设置多任务打卡信息,这个不可能为空,为空则用户初始注册时创建时有问题
+            PiMultiTask piMultiTask = piMultiTaskMap.get(userId);
+            settleData.setPiMultiTask(piMultiTask);
+
+            // 获取并设置对应的拓展信息
+            List<PiMultiTaskExt> tempPiMultiTaskExtList = piMultiTaskExtMap.get(piMultiTask.getId());
+            settleData.setPiMultiTaskExtList(tempPiMultiTaskExtList);
+
+            // 获取并设置对应的多任务打卡记录
+            PiMultiTaskHistory piMultiTaskHistory = piMultiTaskHistoryMap.get(piMultiTask.getUniqueId());
+            settleData.setPiMultiTaskHistory(piMultiTaskHistory);
+
+            // 获取多任务与打卡任务的关联信息
+            List<PiMultiTaskRela> tempPiMultiTaskRelaList = piMultiTaskRelaMap.get(piMultiTask.getId());
+            Set<Long> relaContainTaskIdList =
+                    tempPiMultiTaskRelaList.stream().map(PiMultiTaskRela::getTaskId).collect(Collectors.toSet());
+
+            // 获取并设置多任务的状态信息
+            PiStatus piStatusInMultiTask = piStatusMapInMultiTask.get(piMultiTask.getUniqueId());
+            settleData.setPiStatus(piStatusInMultiTask);
+
+            // 获取任务列表
+            List<PiTask> piTasksList = piTaskMap.get(userId);
+            // 打卡任务数据
+            List<PiTaskData> piTaskDataList = new ArrayList<>(piTasksList.size());
+            // 关联的打卡任务记录
+            List<PiTaskHistory> relaPunchInTaskHistories = new ArrayList<>(relaContainTaskIdList.size());
+
+            for (PiTask piTask : piTasksList) {
+                PiTaskData piTaskData = new PiTaskData();
+                piTaskData.setPiTask(piTask);
+
+                // 获取并设置打卡任务
+                PiTaskHistory piTaskHistory = piTaskHistoryMap.get(piTask.getUniqueId());
+                piTaskData.setPiTaskHistory(piTaskHistory);
+
+                //设置多任务与打卡记录的关联信息
+                if (relaContainTaskIdList.contains(piTask.getId())) {
+                    relaPunchInTaskHistories.add(piTaskHistory);
+                }
+
+                // 获取并设置拓展信息
+                List<PiTaskExt> tempPiTaskExtList = piTaskExtGroupList.get(piTask.getId());
+                piTaskData.setPiTaskExtList(tempPiTaskExtList);
+
+                // 获取并设置任务状态
+                PiStatus piStatusInTask = piStatusMapInTask.get(piTask.getUniqueId());
+                piTaskData.setPiStatus(piStatusInTask);
+
+                piTaskDataList.add(piTaskData);
+            }
+
+            settleData.setPiTaskDataList(piTaskDataList);
+            settleData.setRelaPunchInTaskHistories(relaPunchInTaskHistories);
+
+            return settleData;
+        }).collect(Collectors.toList());
+    }
+
+    /**
+     * 更新打卡任务状态
+     * @param piStatus 打卡任务状态
+     * @param piTask 打卡任务
+     * @param piTaskHistory 打卡任务记录
+     * @param punchInDate 打卡日期
+     * @param isMonday 是否周一
+     * @param isFirstDayOfMonth 是否本月第一天
+     * @param yearWeek 周数
+     * @param yearMonth 月份数
+     */
+    private void refreshPiStatus(PiStatus piStatus, PiTask piTask, PiTaskHistory piTaskHistory, LocalDate punchInDate, boolean isMonday, boolean isFirstDayOfMonth, String yearWeek, String yearMonth) {
+        // 获取打卡结果
+        PunchInResultEnum punchInResult = Objects.isNull(piTaskHistory) ? PunchInResultEnum.UNDONE : piTaskHistory.getPunchInResult();
+
+        // 刷新打卡状态中的连续任务数据
+        refreshContinueData(piStatus, punchInResult, piTask, punchInDate);
+
+        // 周一或月初
+        if (isMonday || isFirstDayOfMonth) {
+            piStatus.setRepeatCategory(piTask.getRepeatCategory());
+            piStatus.setRepeatCustomDay(piTask.getRepeatCustomDay());
+        }
+
+        // 周一
+        if (isMonday) {
+            piStatus.setStatTimeInWeek(yearWeek);
+
+            // 设置本周总打卡次数
+            int PunchInTotalCountInWeek = punchInCoreManager.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) {
+            piStatus.setStatTimeInMonth(yearMonth);
+
+            // 设置本月总打卡次数
+            int PunchInTotalCountInMonth = punchInCoreManager.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 = punchInCoreManager.getPunchInTotalCountInRange(piStatus.getRepeatCategory(),
+                    piStatus.getRepeatCustomDay(), piStatus.getRepeatStartDateInWeek(),
+                    punchInDate.minusDays(1));
+            // 变换后可能的总打卡次数(周)
+            int punchInTotalCountInWeek = punchInCoreManager.getPunchInTotalCountInRange(piTask.getRepeatCategory(), piTask.getRepeatCustomDay(), punchInDate, DateUtils.getLastDayOfWeek(punchInDate));
+
+            // 历史真实发生的总打卡次数(月)
+            Integer oldPrevTotalCountInMonth = Optional.ofNullable(piStatus.getRepeatPrevTotalCountInMonth()).orElse(0);
+            // 变换前发生的总打卡次数(月)
+            int prevTotalCountInMonth = punchInCoreManager.getPunchInTotalCountInRange(piStatus.getRepeatCategory(),
+                    piStatus.getRepeatCustomDay(), piStatus.getRepeatStartDateInMonth(),
+                    punchInDate.minusDays(1));
+            // 变换后可能的总打卡次数(月 )
+            int punchInTotalCountInMonth = punchInCoreManager.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
+        if (Objects.nonNull(piTaskHistory)) {
+            piStatus.setPunchInCountInWeek(piStatus.getPunchInCountInWeek() + 1);
+            piStatus.setPunchInCountInMonth(piStatus.getPunchInCountInMonth() + 1);
+        }
+
+        // 完成打卡则完成打卡数记录加一
+        if (PunchInResultEnum.DONE.equals(punchInResult)) {
+            piStatus.setPunchInDoneCountInWeek(piStatus.getPunchInDoneCountInWeek() + 1);
+            piStatus.setPunchInDoneCountInMonth(piStatus.getPunchInDoneCountInMonth() + 1);
+        }
+    }
+
+    /**
+     * 刷新打卡状态中的连续任务数据
+     * @param piStatus
+     * @param punchInResult
+     * @param continueTask
+     * @param punchInDate
+     */
+    private void refreshContinueData(PiStatus piStatus, PunchInResultEnum punchInResult, ContinueTask continueTask, LocalDate punchInDate) {
+        // 设置任务连续状态
+        ContinueStatusEnum oldTaskContinueStatus = piStatus.getTaskContinueStatus();
+        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 =
+                punchInCoreManager.judgeContinueStage(continueTask, punchInResult, piStatus, punchInDate);
+        piStatus.setContinueStage(continueStageResult);
+        // 下面3种情况不处理:宽限期 变 宽限期;正常打卡期 变 正常打卡期;惩罚期 变 惩罚期;
+        // 宽限期 变 正常打卡期,则设置阶段开始时间,重置中断次数
+        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)) {
+            piStatus.setStageStartDate(punchInDate);
+            piStatus.setStageEndDate(punchInDate.plusDays(continueTask.getPenaltyDay()));
+            piStatus.setContinueInterruptedCount(piStatus.getContinueInterruptedCount() + 1);
+        }
+        // 如果惩罚期 变 正常打卡期,则设置阶段开始时间
+        if (ContinueStageEnum.PENALTY_STAGE.equals(oldContinueStage)
+                && ContinueStageEnum.NORMAL_STAGE.equals(continueStageResult)) {
+            piStatus.setStageStartDate(punchInDate);
+        }
+    }
 }

+ 30 - 0
src/main/java/com/punchsettle/server/service/manager/impl/SettleTaskRelaHistoryServiceImpl.java

@@ -0,0 +1,30 @@
+package com.punchsettle.server.service.manager.impl;
+
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import com.punchsettle.server.atomic.entity.SettleTaskRelaHistory;
+import com.punchsettle.server.atomic.mapper.SettleTaskRelaHistoryMapper;
+import com.punchsettle.server.atomic.service.ISettleTaskRelaHistoryService;
+import com.punchsettle.server.common.utils.Assert;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @date 2025/5/6 18:05
+ * @description 结算任务关联记录 service
+ */
+@Component
+public class SettleTaskRelaHistoryServiceImpl implements ISettleTaskRelaHistoryService {
+
+    @Autowired
+    private SettleTaskRelaHistoryMapper settleTaskRelaHistoryMapper;
+
+    @Override
+    public void insertList(List<SettleTaskRelaHistory> settleTaskRelaHistories) {
+        Assert.notEmpty(settleTaskRelaHistories);
+        settleTaskRelaHistoryMapper.insertList(settleTaskRelaHistories);
+    }
+}

+ 149 - 0
src/main/java/com/punchsettle/server/task/PointsDistributeTask.java

@@ -0,0 +1,149 @@
+package com.punchsettle.server.task;
+
+import com.punchsettle.server.atomic.entity.Account;
+import com.punchsettle.server.atomic.entity.AccountTransferHistory;
+import com.punchsettle.server.atomic.entity.SettleUserHistory;
+import com.punchsettle.server.atomic.entity.User;
+import com.punchsettle.server.atomic.service.IAccountService;
+import com.punchsettle.server.atomic.service.IAccountTransferHistoryService;
+import com.punchsettle.server.atomic.service.ISettleUserHistoryService;
+import com.punchsettle.server.atomic.service.IUserService;
+import com.punchsettle.server.constant.AccountCategoryEnum;
+import com.punchsettle.server.constant.TransferCategoryEnum;
+import com.punchsettle.server.pojo.account.AccountQuery;
+import com.punchsettle.server.pojo.settle.SettleUserHistoryQuery;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.util.CollectionUtils;
+
+import java.time.LocalDate;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Function;
+import java.util.stream.Collectors;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @date 2025/5/6 19:31
+ * @description 积分分发 定时任务
+ */
+@Slf4j
+@Component
+public class PointsDistributeTask {
+
+    @Autowired
+    private ISettleUserHistoryService settleUserHistoryService;
+
+    @Autowired
+    private IUserService userService;
+
+    @Autowired
+    private IAccountService accountService;
+
+    @Autowired
+    private IAccountTransferHistoryService accountTransferHistoryService;
+
+    public void execute() {
+        log.info("========== 积分分发定时任务 开始执行 ==========");
+        // 结算日期
+        LocalDate settleDate = LocalDate.now().minusDays(1);
+
+        // 查询结算记录
+        SettleUserHistoryQuery settleUserHistoryQuery = new SettleUserHistoryQuery();
+        settleUserHistoryQuery.setSettleDate(settleDate.toString());
+        List<SettleUserHistory> settleUserHistories = settleUserHistoryService.querySettleUserHistory(settleUserHistoryQuery);
+
+        if (CollectionUtils.isEmpty(settleUserHistories)) {
+            log.info("========== 积分分发定时任务,没有可分发的积分 结束执行 ==========");
+            return;
+        }
+
+        // 用户ID-用户结算记录关联
+        Map<Long, SettleUserHistory> settleUserHistoryMap = settleUserHistories.stream().collect(Collectors.toMap(SettleUserHistory::getUserId, Function.identity(), (key1, key2) -> key1));
+        // 用户ID列表
+        Set<Long> userIds = settleUserHistories.stream().map(SettleUserHistory::getUserId).collect(Collectors.toSet());
+
+        // 用户信息, 用户ID-用户信息关联
+        List<User> users = userService.listByIds(userIds);
+        Map<Long, User> userMap = users.stream().collect(Collectors.toMap(User::getId, Function.identity(), (key1, key2) -> key1));
+
+        // 获取账户信息,用户ID-账户信息关联
+        AccountQuery accountQuery = new AccountQuery();
+        accountQuery.setAccountCategory(AccountCategoryEnum.BASIC);
+        accountQuery.setUserIds(userIds);
+        List<Account> accounts = accountService.getAccountByCondition(accountQuery);
+        Map<Long, Account> accountMap = accounts.stream().collect(Collectors.toMap(Account::getUserId, Function.identity(), (key1, key2) -> key1));
+
+        // 用户信息 更新列表
+        List<User> updateUserList = new ArrayList<>();
+        // 账户信息 更新列表
+        List<Account> updateAccountList = new ArrayList<>();
+        // 转账记录 新增列表
+        List<AccountTransferHistory> addAccountTransferHistories = new ArrayList<>();
+        // 结算用户信息 更新列表
+        List<SettleUserHistory> updateSettleUserHistories = new ArrayList<>();
+
+        for (Long userId : userIds) {
+            // 用户信息
+            User user = userMap.get(userId);
+            // 账户信息
+            Account account = accountMap.get(userId);
+            // 结算信息
+            SettleUserHistory settleUserHistory = settleUserHistoryMap.get(userId);
+            // 结算积分
+            Integer settlePoints = Optional.ofNullable(settleUserHistory.getSettlePoints()).orElse(0);
+
+            // 获取并设置用户信息
+            Integer beforeTotalPoints = Optional.ofNullable(user.getTotalPoints()).orElse(0);
+            Integer beforeUnusedPoints = Optional.ofNullable(user.getUnusedPoints()).orElse(0);
+            User updateUser = new User();
+            updateUser.setId(user.getId());
+            updateUser.setTotalPoints(beforeTotalPoints + settlePoints);
+            updateUser.setUnusedPoints(beforeUnusedPoints + settlePoints);
+            updateUserList.add(user);
+
+            // 更新账户信息
+            Integer beforeAccountPoints = Optional.ofNullable(account.getPoints()).orElse(0);
+            account.setPoints(beforeAccountPoints + settlePoints);
+            updateAccountList.add(account);
+
+            // 增加账户转账记录
+            AccountTransferHistory accountTransferHistory = new AccountTransferHistory();
+            accountTransferHistory.setTransferPoints(settlePoints);
+            accountTransferHistory.setTransferCategory(TransferCategoryEnum.SETTLE);
+            accountTransferHistory.setRecipientAccountId(account.getId());
+            accountTransferHistory.setRaPointsAfterTransfer(beforeAccountPoints);
+            accountTransferHistory.setRaPointsAfterTransfer(account.getPoints());
+            addAccountTransferHistories.add(accountTransferHistory);
+
+            // 设置结算积分记录
+            SettleUserHistory updateSettleUserHistory = new SettleUserHistory();
+            updateSettleUserHistory.setBeforeSettlePoints(beforeTotalPoints);
+            updateSettleUserHistory.setAfterSettlePoints(beforeTotalPoints + settlePoints);
+            updateSettleUserHistories.add(updateSettleUserHistory);
+        }
+
+        if (!CollectionUtils.isEmpty(updateUserList)) {
+            userService.batchUpdate(updateUserList);
+        }
+
+        if (!CollectionUtils.isEmpty(updateAccountList)) {
+            accountService.batchUpdate(updateAccountList);
+        }
+
+        if (!CollectionUtils.isEmpty(addAccountTransferHistories)) {
+            accountTransferHistoryService.insertList(addAccountTransferHistories);
+        }
+
+        if (!CollectionUtils.isEmpty(updateSettleUserHistories)) {
+            settleUserHistoryService.insertList(updateSettleUserHistories);
+        }
+
+        log.info("========== 积分分发定时任务 结束执行 ==========");
+    }
+}

+ 85 - 0
src/main/java/com/punchsettle/server/task/PointsSettleTask.java

@@ -0,0 +1,85 @@
+package com.punchsettle.server.task;
+
+import com.google.common.collect.Lists;
+import com.punchsettle.server.atomic.entity.SettleTaskHistory;
+import com.punchsettle.server.atomic.service.ISettleTaskHistoryService;
+import com.punchsettle.server.atomic.service.IUserService;
+import com.punchsettle.server.service.manager.ISettleManager;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.util.CollectionUtils;
+
+import java.time.LocalDate;
+import java.util.List;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @date 2025/4/15 16:24
+ * @description 结算定时任务
+ */
+@Slf4j
+@Component
+public class PointsSettleTask {
+
+    @Autowired
+    private IUserService userService;
+
+    @Autowired
+    private ISettleTaskHistoryService settleTaskHistoryService;
+
+    @Autowired
+    private ISettleManager settleManager;
+
+    public void execute() {
+        log.info("========== 打卡结算定时任务 开始执行 ==========");
+
+        List<Long> userIds = userService.listId();
+        if (CollectionUtils.isEmpty(userIds)) {
+            log.info("========== 打卡结算定时任务,没有待结算用户 结束执行 ==========");
+            return;
+        }
+
+        // 打卡日期
+        LocalDate punchInDate = LocalDate.now().minusDays(1);
+
+        // 数据入库
+        SettleTaskHistory addSettleTaskHistory = new SettleTaskHistory();
+        addSettleTaskHistory.setSettleDate(punchInDate.toString());
+        addSettleTaskHistory.setProcessedTotalNum(userIds.size());
+        addSettleTaskHistory.setProcessedUnsettleNum(userIds.size());
+        addSettleTaskHistory.setProcessedSettleNum(0);
+        settleTaskHistoryService.insert(addSettleTaskHistory);
+
+        // 批处理数量
+        int batchNum = 20;
+        // 未结算数量
+        int unsettleNum = userIds.size();
+        // 已结算数量
+        int settleNum = 0;
+
+
+        for (List<Long> tempUserIds : Lists.partition(userIds, batchNum)) {
+            try {
+                // 结算
+                settleManager.settle(tempUserIds, punchInDate.toString(), addSettleTaskHistory.getId());
+
+                // 更新结算数量
+                unsettleNum -= batchNum;
+                settleNum += batchNum;
+
+                // 更新数据记录
+                SettleTaskHistory updateSettleTaskHistory = new SettleTaskHistory();
+                updateSettleTaskHistory.setId(addSettleTaskHistory.getId());
+                updateSettleTaskHistory.setProcessedUnsettleNum(unsettleNum);
+                updateSettleTaskHistory.setProcessedSettleNum(settleNum);
+                settleTaskHistoryService.update(updateSettleTaskHistory);
+            } catch (Exception e) {
+                log.error("结算异常", e);
+            }
+        }
+
+        log.info("========== 打卡结算定时任务 结束执行 ==========");
+    }
+}

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

@@ -1,50 +0,0 @@
-package com.punchsettle.server.task;
-
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.stereotype.Component;
-
-/**
- * @author tyuio
- * @version 1.0.0
- * @date 2025/4/15 16:24
- * @description 打卡定时任务
- */
-@Slf4j
-@Component
-public class PunchInCoreTask {
-
-
-
-    public void execute() {
-        log.info("========== 打卡定时任务 开始执行 ==========");
-
-        log.info("========== 打卡定时任务 结束执行 ==========");
-    }
-
-    // public void punchInInTask(PunchInTask punchInTask, List<PunchInTaskExt> punchInTaskExtList,
-    // PunchInTaskHistory punchInTaskHistory,
-    // PunchInStatsWeek punchInStatsWeek, PunchInStatsMonth punchInStatsMonth, PunchInStatus punchInStatus,
-    // ) {
-    //
-    // PunchInStatusEnum punchInStatusEnum = punchInManager.judgePunchInStatusInTask(punchInTask, punchInTaskHistory);
-    //
-    // int taskPoints = settleManager.calculatePointsInTask(punchInTask, punchInTaskExtList, punchInTaskHistory,
-    // punchInStatsWeek, punchInStatsMonth, punchInStatus);
-    //
-    // }
-    //
-    // public void punchInInMultiTask(PunchInStatus punchInStatus,
-    // List<PunchInTaskHistory> punchInTaskHistoryList,
-    // PunchInMultiTask punchInMultiTask, List<PunchInMultiTaskExt> punchInMultiTaskExtList,
-    // PunchInMultiTaskHistory punchInMultiTaskHistory) {
-    //
-    // PunchInStatusEnum punchInStatusEnum1 =
-    // punchInManager.judgePunchInStatusInMultiTask(punchInMultiTask, punchInTaskHistoryList);
-    //
-    // int multiTaskPoints = settleManager.calculatePointsInMultiTask(punchInMultiTask, punchInMultiTaskExtList,
-    // punchInMultiTaskHistory, punchInStatus);
-    //
-    // }
-
-
-}

+ 23 - 0
src/main/java/com/punchsettle/server/task/StatNewUserTask.java

@@ -0,0 +1,23 @@
+package com.punchsettle.server.task;
+
+import com.punchsettle.server.atomic.service.IStatNewUserService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @date 2025/5/6 12:36
+ * @description 新用户数据统计
+ */
+@Component
+public class StatNewUserTask {
+
+    @Autowired
+    private IStatNewUserService statNewUserService;
+
+
+    public void execute() {
+//        statNewUserService.
+    }
+}