Browse Source

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

ChenYL 10 tháng trước cách đây
mục cha
commit
6b5fe5dd0a
37 tập tin đã thay đổi với 1357 bổ sung344 xóa
  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.
+    }
+}