Pārlūkot izejas kodu

【feat】【v3】
1.增加并完善积分统计逻辑

ChenYL 10 mēneši atpakaļ
vecāks
revīzija
8ebebf93ee
22 mainītis faili ar 619 papildinājumiem un 84 dzēšanām
  1. 40 0
      src/main/java/com/punchsettle/server/atomic/IStatPiTaskService.java
  2. 77 8
      src/main/java/com/punchsettle/server/atomic/StatPiTask.java
  3. 2 1
      src/main/java/com/punchsettle/server/atomic/mapper/StatPiTaskMonthMapper.java
  4. 2 1
      src/main/java/com/punchsettle/server/atomic/mapper/StatPiTaskWeekMapper.java
  5. 4 1
      src/main/java/com/punchsettle/server/atomic/mapper/StatPiTaskYearMapper.java
  6. 8 0
      src/main/java/com/punchsettle/server/atomic/service/IPiTaskService.java
  7. 7 0
      src/main/java/com/punchsettle/server/atomic/service/ISettleTaskRelaHistoryService.java
  8. 2 14
      src/main/java/com/punchsettle/server/atomic/service/IStatPiTaskMonthService.java
  9. 2 13
      src/main/java/com/punchsettle/server/atomic/service/IStatPiTaskWeekService.java
  10. 2 9
      src/main/java/com/punchsettle/server/atomic/service/IStatPiTaskYearService.java
  11. 24 7
      src/main/java/com/punchsettle/server/atomic/service/impl/PiTaskServiceImpl.java
  12. 38 10
      src/main/java/com/punchsettle/server/atomic/service/impl/StatPiTaskMonthServiceImpl.java
  13. 40 17
      src/main/java/com/punchsettle/server/atomic/service/impl/StatPiTaskWeekServiceImpl.java
  14. 40 1
      src/main/java/com/punchsettle/server/atomic/service/impl/StatPiTaskYearServiceImpl.java
  15. 47 0
      src/main/java/com/punchsettle/server/pojo/settle/SettleTaskRelaHistoryQuery.java
  16. 12 0
      src/main/java/com/punchsettle/server/pojo/stat/StatPiTaskQuery.java
  17. 5 0
      src/main/java/com/punchsettle/server/pojo/stat/StatPiTaskWeekQuery.java
  18. 17 0
      src/main/java/com/punchsettle/server/service/manager/IStatManager.java
  19. 2 2
      src/main/java/com/punchsettle/server/service/manager/impl/PunchInManagerImpl.java
  20. 34 0
      src/main/java/com/punchsettle/server/service/manager/impl/SettleTaskRelaHistoryServiceImpl.java
  21. 138 0
      src/main/java/com/punchsettle/server/service/manager/impl/StatManagerImpl.java
  22. 76 0
      src/main/java/com/punchsettle/server/task/StatPiTask.java

+ 40 - 0
src/main/java/com/punchsettle/server/atomic/IStatPiTaskService.java

@@ -0,0 +1,40 @@
+package com.punchsettle.server.atomic;
+
+import java.util.List;
+
+import com.punchsettle.server.pojo.stat.StatPiTaskQuery;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @date 2025/5/7 11:08
+ * @description 打卡任务统计 服务类
+ */
+public interface IStatPiTaskService {
+
+    /**
+     * 按条件查询
+     * @param query
+     * @return
+     */
+    StatPiTask queryOneByCondition(StatPiTaskQuery query);
+
+    /**
+     * 按条件查询统计数据
+     * @param statPiTaskQuery
+     * @return
+     */
+    List<StatPiTask> queryByCondition(StatPiTaskQuery statPiTaskQuery);
+
+    /**
+     * 批量新增
+     * @param statPiTaskList
+     */
+    void insertList(List statPiTaskList);
+
+    /**
+     * 批量更新
+     * @param statPiTaskList
+     */
+    void batchUpdate(List statPiTaskList);
+}

+ 77 - 8
src/main/java/com/punchsettle/server/atomic/StatPiTask.java

@@ -11,44 +11,113 @@ import java.math.BigDecimal;
 public interface StatPiTask {
 
     /**
-     * 获取任务唯一ID
+     * 主键ID
+     * @param id
+     */
+    void setId(Long id);
+
+    /**
+     * 主键ID
+     * @return
+     */
+    Long getId();
+
+    /**
+     * 用户ID
+     * @param userId
+     */
+    void setUserId(Long userId);
+
+    /**
+     * 用户ID
+     * @return
+     */
+    Long getUserId();
+
+    /**
+     * 任务唯一ID
+     */
+    void setTaskUniqueId(Long taskUniqueId);
+
+    /**
+     * 任务唯一ID
      * @return
      */
     Long getTaskUniqueId();
 
     /**
-     * 获取统计时间
+     * 统计时间
+     */
+    void setStatTime(String statTime);
+
+    /**
+     * 统计时间
      * @return
      */
     String getStatTime();
 
     /**
-     * 本年需打卡数
+     * 需打卡数
+     * @param punchInTotalCount
+     */
+    void setPunchInTotalCount(Integer punchInTotalCount);
+
+    /**
+     * 需打卡数
      */
     Integer getPunchInTotalCount();
 
     /**
-     * 本年已打卡数
+     * 已打卡数
+     * @param punchInCount
+     */
+    void setPunchInCount(Integer punchInCount);
+
+    /**
+     * 已打卡数
      */
     Integer getPunchInCount();
 
     /**
-     * 本年完成打卡数
+     * 完成打卡数
+     */
+    void setPunchInDoneCount(Integer punchInDoneCount);
+
+    /**
+     * 完成打卡数
      */
     Integer getPunchInDoneCount();
 
     /**
-     * 本年打卡率
+     * 打卡率
+     * @param punchInRate
+     */
+    void setPunchInRate(BigDecimal punchInRate);
+
+    /**
+     * 打卡率
      */
     BigDecimal getPunchInRate();
 
     /**
-     * 本年打卡完成率
+     * 打卡完成率
+     * @param punchInDoneRate
+     */
+    void setPunchInDoneRate(BigDecimal punchInDoneRate);
+
+    /**
+     * 打卡完成率
      */
     BigDecimal getPunchInDoneRate();
 
     /**
-     * 本年获取积分数
+     * 积分
+     * @param points
+     */
+    void setPoints(Integer points);
+
+    /**
+     * 积分
      */
     Integer getPoints();
 }

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

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

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

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

+ 4 - 1
src/main/java/com/punchsettle/server/atomic/mapper/StatPiTaskYearMapper.java

@@ -1,7 +1,10 @@
 package com.punchsettle.server.atomic.mapper;
 
 import com.punchsettle.server.atomic.entity.StatPiTaskYear;
+
+import tk.mybatis.mapper.additional.update.batch.BatchUpdateSelectiveMapper;
 import tk.mybatis.mapper.common.Mapper;
+import tk.mybatis.mapper.common.special.InsertListMapper;
 
 /**
  * @author tyuio
@@ -9,6 +12,6 @@ import tk.mybatis.mapper.common.Mapper;
  * @description 打卡任务年数据统计 Mapper
  * @date 2025/04/08 10:30
  */
-public interface StatPiTaskYearMapper extends Mapper<StatPiTaskYear> {
+public interface StatPiTaskYearMapper extends Mapper<StatPiTaskYear>, InsertListMapper<StatPiTaskYear>, BatchUpdateSelectiveMapper<StatPiTaskYear> {
 
 }

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

@@ -3,6 +3,7 @@ package com.punchsettle.server.atomic.service;
 import com.punchsettle.server.atomic.entity.PiTask;
 import com.punchsettle.server.pojo.punchIn.PiTaskQuery;
 
+import java.util.Collection;
 import java.util.List;
 
 /**
@@ -38,4 +39,11 @@ public interface IPiTaskService {
      * @param piTask
      */
     void update(PiTask piTask);
+
+    /**
+     * 按条件获取有效的任务列表
+     * @param userIds
+     * @return
+     */
+    List<PiTask> getActiveTask(Collection<Long> userIds);
 }

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

@@ -1,6 +1,7 @@
 package com.punchsettle.server.atomic.service;
 
 import com.punchsettle.server.atomic.entity.SettleTaskRelaHistory;
+import com.punchsettle.server.pojo.settle.SettleTaskRelaHistoryQuery;
 
 import java.util.List;
 
@@ -17,4 +18,10 @@ public interface ISettleTaskRelaHistoryService {
      * @param settleTaskRelaHistories
      */
     void insertList(List<SettleTaskRelaHistory> settleTaskRelaHistories);
+
+    /**
+     * 按条件查询
+     * @return
+     */
+    List<SettleTaskRelaHistory> queryByCondition(SettleTaskRelaHistoryQuery query);
 }

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

@@ -1,5 +1,6 @@
 package com.punchsettle.server.atomic.service;
 
+import com.punchsettle.server.atomic.IStatPiTaskService;
 import com.punchsettle.server.atomic.entity.StatPiTaskMonth;
 import com.punchsettle.server.pojo.punchIn.PiStatsMonthQuery;
 import com.punchsettle.server.pojo.stat.StatPiTaskQuery;
@@ -12,7 +13,7 @@ import java.util.List;
  * @date 2025/4/8 10:37
  * @description 打卡任务月数据统计 service
  */
-public interface IStatPiTaskMonthService {
+public interface IStatPiTaskMonthService extends IStatPiTaskService {
 
     /**
      * 根据条件查询打卡任务月数据统计
@@ -20,17 +21,4 @@ public interface IStatPiTaskMonthService {
      * @return
      */
     List<StatPiTaskMonth> queryByCondition(PiStatsMonthQuery piStatsMonthQuery);
-
-    /**
-     * 批量新增
-     * @param statPiTaskMonthList
-     */
-    void insertList(List<StatPiTaskMonth> statPiTaskMonthList);
-
-    /**
-     * 查询统计数据
-     * @param query 查询条件
-     * @return
-     */
-    StatPiTaskMonth queryByCondition(StatPiTaskQuery query);
 }

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

@@ -1,5 +1,6 @@
 package com.punchsettle.server.atomic.service;
 
+import com.punchsettle.server.atomic.IStatPiTaskService;
 import com.punchsettle.server.atomic.entity.StatPiTaskWeek;
 import com.punchsettle.server.pojo.stat.StatPiTaskWeekQuery;
 
@@ -11,18 +12,6 @@ import java.util.List;
  * @date 2025/4/8 10:37
  * @description 打卡任务周数据统计 service
  */
-public interface IStatPiTaskWeekService {
+public interface IStatPiTaskWeekService extends IStatPiTaskService {
 
-    /**
-     * 根据条件查询打卡任务周数据统计
-     * @param statPiTaskWeekQuery
-     * @return
-     */
-    List<StatPiTaskWeek> queryByCondition(StatPiTaskWeekQuery statPiTaskWeekQuery);
-
-    /**
-     * 批量新增
-     * @param statPiTaskWeekList
-     */
-    void insertList(List<StatPiTaskWeek> statPiTaskWeekList);
 }

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

@@ -1,7 +1,6 @@
 package com.punchsettle.server.atomic.service;
 
-import com.punchsettle.server.atomic.entity.StatPiTaskYear;
-import com.punchsettle.server.pojo.stat.StatPiTaskQuery;
+import com.punchsettle.server.atomic.IStatPiTaskService;
 
 /**
  * @author tyuio
@@ -9,12 +8,6 @@ import com.punchsettle.server.pojo.stat.StatPiTaskQuery;
  * @date 2025/4/8 10:37
  * @description 打卡任务年数据统计 service
  */
-public interface IStatPiTaskYearService {
+public interface IStatPiTaskYearService extends IStatPiTaskService {
 
-    /**
-     * 按条件查询年统计数据
-     * @param query 查询条件
-     * @return
-     */
-    StatPiTaskYear queryByCondition(StatPiTaskQuery query);
 }

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

@@ -1,21 +1,25 @@
 package com.punchsettle.server.atomic.service.impl;
 
+import java.util.Collection;
+import java.util.List;
+import java.util.Objects;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+
 import com.punchsettle.server.atomic.entity.PiTask;
 import com.punchsettle.server.atomic.mapper.PiTaskMapper;
 import com.punchsettle.server.atomic.service.IPiTaskService;
 import com.punchsettle.server.common.pojo.BaseEntity;
 import com.punchsettle.server.common.utils.Assert;
+import com.punchsettle.server.constant.ArchiveStatusEnum;
+import com.punchsettle.server.constant.VersionStatusEnum;
 import com.punchsettle.server.pojo.punchIn.PiTaskQuery;
-import com.punchsettle.server.utiis.WeekendUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import org.springframework.util.CollectionUtils;
+
 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
@@ -76,4 +80,17 @@ public class PiTaskServiceImpl implements IPiTaskService {
         Assert.isNull(piTask);
         piTaskMapper.updateByPrimaryKeySelective(piTask);
     }
+
+    @Override
+    public List<PiTask> getActiveTask(Collection<Long> userIds) {
+        if (CollectionUtils.isEmpty(userIds)) {
+            return List.of();
+        }
+
+        PiTaskQuery piTaskQuery = new PiTaskQuery();
+        piTaskQuery.setTaskStatus(VersionStatusEnum.ACTIVE);
+        piTaskQuery.setArchiveStatus(ArchiveStatusEnum.ACTIVE);
+        piTaskQuery.setUserIds(userIds);
+        return queryByCondition(piTaskQuery);
+    }
 }

+ 38 - 10
src/main/java/com/punchsettle/server/atomic/service/impl/StatPiTaskMonthServiceImpl.java

@@ -1,21 +1,25 @@
 package com.punchsettle.server.atomic.service.impl;
 
+import java.util.List;
+import java.util.Objects;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+
+import com.punchsettle.server.atomic.StatPiTask;
 import com.punchsettle.server.atomic.entity.StatPiTaskMonth;
+import com.punchsettle.server.atomic.entity.StatPiTaskWeek;
 import com.punchsettle.server.atomic.mapper.StatPiTaskMonthMapper;
 import com.punchsettle.server.atomic.service.IStatPiTaskMonthService;
 import com.punchsettle.server.common.utils.Assert;
 import com.punchsettle.server.pojo.punchIn.PiStatsMonthQuery;
 import com.punchsettle.server.pojo.stat.StatPiTaskQuery;
 import com.punchsettle.server.utiis.WeekendUtils;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import org.springframework.util.CollectionUtils;
+
 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
@@ -44,13 +48,37 @@ public class StatPiTaskMonthServiceImpl implements IStatPiTaskMonthService {
     }
 
     @Override
-    public void insertList(List<StatPiTaskMonth> statPiTaskMonthList) {
-        Assert.notEmpty(statPiTaskMonthList);
-        statPiTaskMonthMapper.insertList(statPiTaskMonthList);
+    public void insertList(List statPiTaskList) {
+        Assert.notEmpty(statPiTaskList);
+        statPiTaskMonthMapper.insertList(statPiTaskList);
+    }
+
+    @Override
+    public void batchUpdate(List statPiTaskList) {
+        Assert.notEmpty(statPiTaskList);
+        statPiTaskMonthMapper.batchUpdateSelective(statPiTaskList);
+    }
+
+    @Override
+    public List<StatPiTask> queryByCondition(StatPiTaskQuery statPiTaskQuery) {
+        Assert.isNull(statPiTaskQuery);
+
+        Weekend<StatPiTaskWeek> weekend = WeekendUtils.createExcludeAuditFields(StatPiTaskWeek.class);
+        WeekendCriteria<StatPiTaskWeek, Object> criteria = weekend.weekendCriteria();
+        if (!CollectionUtils.isEmpty(statPiTaskQuery.getTaskUniqueIds())) {
+            criteria.andIn(StatPiTaskWeek::getTaskUniqueId, statPiTaskQuery.getTaskUniqueIds());
+        }
+        if (Objects.nonNull(statPiTaskQuery.getStatTime())) {
+            criteria.andEqualTo(StatPiTaskWeek::getStatTime, statPiTaskQuery.getStatTime());
+        }
+        if (!CollectionUtils.isEmpty(statPiTaskQuery.getUserIds())) {
+            criteria.andIn(StatPiTaskWeek::getUserId, statPiTaskQuery.getUserIds());
+        }
+        return (List) statPiTaskMonthMapper.selectByExample(weekend);
     }
 
     @Override
-    public StatPiTaskMonth queryByCondition(StatPiTaskQuery query) {
+    public StatPiTask queryOneByCondition(StatPiTaskQuery query) {
         Assert.isNull(query);
 
         StatPiTaskMonth statPiTaskMonthQuery = new StatPiTaskMonth();

+ 40 - 17
src/main/java/com/punchsettle/server/atomic/service/impl/StatPiTaskWeekServiceImpl.java

@@ -1,21 +1,24 @@
 package com.punchsettle.server.atomic.service.impl;
 
+import java.util.List;
+import java.util.Objects;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+
+import com.punchsettle.server.atomic.StatPiTask;
 import com.punchsettle.server.atomic.entity.StatPiTaskWeek;
 import com.punchsettle.server.atomic.mapper.StatPiTaskWeekMapper;
 import com.punchsettle.server.atomic.service.IStatPiTaskWeekService;
 import com.punchsettle.server.common.utils.Assert;
-import com.punchsettle.server.pojo.stat.StatPiTaskWeekQuery;
+import com.punchsettle.server.pojo.stat.StatPiTaskQuery;
 import com.punchsettle.server.utiis.WeekendUtils;
+
 import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Service;
-import org.springframework.util.CollectionUtils;
 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
@@ -30,23 +33,43 @@ public class StatPiTaskWeekServiceImpl implements IStatPiTaskWeekService {
     private StatPiTaskWeekMapper statPiTaskWeekMapper;
 
     @Override
-    public List<StatPiTaskWeek> queryByCondition(StatPiTaskWeekQuery statPiTaskWeekQuery) {
-        Assert.isNull(statPiTaskWeekQuery);
+    public StatPiTask queryOneByCondition(StatPiTaskQuery query) {
+        Assert.isNull(query);
+
+        StatPiTaskWeek statPiTaskWeekQuery = new StatPiTaskWeek();
+        statPiTaskWeekQuery.setUserId(query.getUserId());
+        statPiTaskWeekQuery.setStatTime(query.getStatTime());
+        statPiTaskWeekQuery.setTaskUniqueId(query.getTaskUniqueId());
+        return statPiTaskWeekMapper.selectOne(statPiTaskWeekQuery);
+    }
+
+    @Override
+    public List<StatPiTask> queryByCondition(StatPiTaskQuery statPiTaskQuery) {
+        Assert.isNull(statPiTaskQuery);
 
         Weekend<StatPiTaskWeek> weekend = WeekendUtils.createExcludeAuditFields(StatPiTaskWeek.class);
         WeekendCriteria<StatPiTaskWeek, Object> criteria = weekend.weekendCriteria();
-        if (!CollectionUtils.isEmpty(statPiTaskWeekQuery.getTaskUniqueIds())) {
-            criteria.andIn(StatPiTaskWeek::getTaskUniqueId, statPiTaskWeekQuery.getTaskUniqueIds());
+        if (!CollectionUtils.isEmpty(statPiTaskQuery.getTaskUniqueIds())) {
+            criteria.andIn(StatPiTaskWeek::getTaskUniqueId, statPiTaskQuery.getTaskUniqueIds());
+        }
+        if (Objects.nonNull(statPiTaskQuery.getStatTime())) {
+            criteria.andEqualTo(StatPiTaskWeek::getStatTime, statPiTaskQuery.getStatTime());
         }
-        if (Objects.nonNull(statPiTaskWeekQuery.getStatsTime())) {
-            criteria.andEqualTo(StatPiTaskWeek::getStatTime, statPiTaskWeekQuery.getStatsTime());
+        if (!CollectionUtils.isEmpty(statPiTaskQuery.getUserIds())) {
+            criteria.andIn(StatPiTaskWeek::getUserId, statPiTaskQuery.getUserIds());
         }
-        return statPiTaskWeekMapper.selectByExample(weekend);
+        return (List) statPiTaskWeekMapper.selectByExample(weekend);
+    }
+
+    @Override
+    public void insertList(List statPiTaskList) {
+        Assert.notEmpty(statPiTaskList);
+        statPiTaskWeekMapper.insertList(statPiTaskList);
     }
 
     @Override
-    public void insertList(List<StatPiTaskWeek> statPiTaskWeekList) {
-        Assert.notEmpty(statPiTaskWeekList);
-        statPiTaskWeekMapper.insertList(statPiTaskWeekList);
+    public void batchUpdate(List statPiTaskList) {
+        Assert.notEmpty(statPiTaskList);
+        statPiTaskWeekMapper.batchUpdateSelective(statPiTaskList);
     }
 }

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

@@ -1,12 +1,21 @@
 package com.punchsettle.server.atomic.service.impl;
 
+import com.punchsettle.server.atomic.StatPiTask;
+import com.punchsettle.server.atomic.entity.StatPiTaskWeek;
 import com.punchsettle.server.atomic.entity.StatPiTaskYear;
 import com.punchsettle.server.atomic.mapper.StatPiTaskYearMapper;
 import com.punchsettle.server.atomic.service.IStatPiTaskYearService;
 import com.punchsettle.server.common.utils.Assert;
 import com.punchsettle.server.pojo.stat.StatPiTaskQuery;
+import com.punchsettle.server.utiis.WeekendUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+import tk.mybatis.mapper.weekend.Weekend;
+import tk.mybatis.mapper.weekend.WeekendCriteria;
+
+import java.util.List;
+import java.util.Objects;
 
 /**
  * @author tyuio
@@ -21,7 +30,7 @@ public class StatPiTaskYearServiceImpl implements IStatPiTaskYearService {
     private StatPiTaskYearMapper statPiTaskYearMapper;
 
     @Override
-    public StatPiTaskYear queryByCondition(StatPiTaskQuery query) {
+    public StatPiTask queryOneByCondition(StatPiTaskQuery query) {
         Assert.isNull(query);
 
         StatPiTaskYear statPiTaskYearQuery = new StatPiTaskYear();
@@ -30,4 +39,34 @@ public class StatPiTaskYearServiceImpl implements IStatPiTaskYearService {
         statPiTaskYearQuery.setTaskUniqueId(query.getTaskUniqueId());
         return statPiTaskYearMapper.selectOne(statPiTaskYearQuery);
     }
+
+    @Override
+    public List<StatPiTask> queryByCondition(StatPiTaskQuery statPiTaskQuery) {
+        Assert.isNull(statPiTaskQuery);
+
+        Weekend<StatPiTaskWeek> weekend = WeekendUtils.createExcludeAuditFields(StatPiTaskWeek.class);
+        WeekendCriteria<StatPiTaskWeek, Object> criteria = weekend.weekendCriteria();
+        if (!CollectionUtils.isEmpty(statPiTaskQuery.getTaskUniqueIds())) {
+            criteria.andIn(StatPiTaskWeek::getTaskUniqueId, statPiTaskQuery.getTaskUniqueIds());
+        }
+        if (Objects.nonNull(statPiTaskQuery.getStatTime())) {
+            criteria.andEqualTo(StatPiTaskWeek::getStatTime, statPiTaskQuery.getStatTime());
+        }
+        if (!CollectionUtils.isEmpty(statPiTaskQuery.getUserIds())) {
+            criteria.andIn(StatPiTaskWeek::getUserId, statPiTaskQuery.getUserIds());
+        }
+        return (List) statPiTaskYearMapper.selectByExample(weekend);
+    }
+
+    @Override
+    public void insertList(List statPiTaskList) {
+        Assert.notEmpty(statPiTaskList);
+        statPiTaskYearMapper.insertList(statPiTaskList);
+    }
+
+    @Override
+    public void batchUpdate(List statPiTaskList) {
+        Assert.notEmpty(statPiTaskList);
+        statPiTaskYearMapper.batchUpdateSelective(statPiTaskList);
+    }
 }

+ 47 - 0
src/main/java/com/punchsettle/server/pojo/settle/SettleTaskRelaHistoryQuery.java

@@ -0,0 +1,47 @@
+package com.punchsettle.server.pojo.settle;
+
+import com.punchsettle.server.constant.SettleResultEnum;
+import lombok.Data;
+
+import java.util.Collection;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @date 2025/5/6 21:53
+ * @description 结算任务关联记录 查询
+ */
+@Data
+public class SettleTaskRelaHistoryQuery {
+
+    /**
+     * 用户ID列表
+     */
+    private Collection<Long> userIds;
+
+    /**
+     * 结算日期(右模糊)
+     */
+    private String settleDateLike;
+
+    /**
+     * 结算日期
+     */
+    private String settleDate;
+
+    /**
+     * 结算日期(开始)
+     */
+    private String settleDateFrom;
+
+    /**
+     * 结算日期(结束)
+     */
+    private String settleDateTo;
+
+    /**
+     * 结算状态
+     * @see SettleResultEnum
+     */
+    private SettleResultEnum settleResult;
+}

+ 12 - 0
src/main/java/com/punchsettle/server/pojo/stat/StatPiTaskQuery.java

@@ -2,6 +2,8 @@ package com.punchsettle.server.pojo.stat;
 
 import lombok.Data;
 
+import java.util.List;
+
 /**
  * @author tyuio
  * @version 1.0.0
@@ -16,11 +18,21 @@ public class StatPiTaskQuery {
      */
     private Long userId;
 
+    /**
+     * 用户ID列表
+     */
+    private List<Long> userIds;
+
     /**
      * 任务唯一ID
      */
     private Long taskUniqueId;
 
+    /**
+     * 任务唯一ID列表
+     */
+    private List<Long> taskUniqueIds;
+
     /**
      * 统计时间
      */

+ 5 - 0
src/main/java/com/punchsettle/server/pojo/stat/StatPiTaskWeekQuery.java

@@ -22,4 +22,9 @@ public class StatPiTaskWeekQuery {
      * 统计时间(格式:yyyy-W周数)
      */
     private String statsTime;
+
+    /**
+     * 用户ID列表
+     */
+    private Collection<Long> userIds;
 }

+ 17 - 0
src/main/java/com/punchsettle/server/service/manager/IStatManager.java

@@ -1,7 +1,12 @@
 package com.punchsettle.server.service.manager;
 
+import com.punchsettle.server.atomic.IStatPiTaskService;
+import com.punchsettle.server.constant.StatPeriodEnum;
 import com.punchsettle.server.pojo.ucharts.LineVO;
 
+import java.time.LocalDate;
+import java.util.List;
+
 /**
  * @author myou
  * @version 1.0.0
@@ -27,4 +32,16 @@ public interface IStatManager {
      * @return
      */
     LineVO queryStatTaskLine();
+
+    /**
+     * 统计打卡任务数据
+     * @param statPiTaskService 统计数据操作类
+     * @param statPeriod 统计周期
+     * @param userIds 用户ID列表
+     * @param statTime 统计时间
+     * @param statFirstDay 统计范围的第一天
+     * @param statLastDay 统计范围的最后一天
+     */
+    void statPiTaskData(IStatPiTaskService statPiTaskService, StatPeriodEnum statPeriod, List<Long> userIds, LocalDate statTime, LocalDate statFirstDay, LocalDate statLastDay);
+
 }

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

@@ -561,9 +561,9 @@ public class PunchInManagerImpl implements IPunchInManager {
         // 查询统计数据
         StatPiTask statPiTask = null;
         if (StatPeriodEnum.YEAR.equals(query.getStatPeriod())) {
-            statPiTask = statPiTaskYearService.queryByCondition(statPiTaskQuery);
+            statPiTask = statPiTaskYearService.queryOneByCondition(statPiTaskQuery);
         } else if (StatPeriodEnum.MONTH.equals(query.getStatPeriod())) {
-            statPiTask = statPiTaskMonthService.queryByCondition(statPiTaskQuery);
+            statPiTask = statPiTaskMonthService.queryOneByCondition(statPiTaskQuery);
         }
 
         if (Objects.isNull(statPiTask)) {

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

@@ -1,7 +1,10 @@
 package com.punchsettle.server.service.manager.impl;
 
 import java.util.List;
+import java.util.Objects;
 
+import com.punchsettle.server.pojo.settle.SettleTaskRelaHistoryQuery;
+import com.punchsettle.server.utiis.WeekendUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Component;
 
@@ -9,6 +12,10 @@ 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;
+import org.springframework.util.CollectionUtils;
+import org.springframework.util.StringUtils;
+import tk.mybatis.mapper.weekend.Weekend;
+import tk.mybatis.mapper.weekend.WeekendCriteria;
 
 /**
  * @author tyuio
@@ -27,4 +34,31 @@ public class SettleTaskRelaHistoryServiceImpl implements ISettleTaskRelaHistoryS
         Assert.notEmpty(settleTaskRelaHistories);
         settleTaskRelaHistoryMapper.insertList(settleTaskRelaHistories);
     }
+
+    @Override
+    public List<SettleTaskRelaHistory> queryByCondition(SettleTaskRelaHistoryQuery query) {
+        Assert.isNull(query);
+
+        Weekend<SettleTaskRelaHistory> weekend = WeekendUtils.createExcludeAuditFields(SettleTaskRelaHistory.class);
+        WeekendCriteria<SettleTaskRelaHistory, Object> criteria = weekend.weekendCriteria();
+        if (!CollectionUtils.isEmpty(query.getUserIds())) {
+            criteria.andIn(SettleTaskRelaHistory::getId, query.getUserIds());
+        }
+        if (StringUtils.hasText(query.getSettleDateLike())) {
+            criteria.andLike(SettleTaskRelaHistory::getSettleDate, String.format("%s%%", query.getSettleDateLike()));
+        }
+        if (StringUtils.hasText(query.getSettleDate())) {
+            criteria.andEqualTo(SettleTaskRelaHistory::getSettleDate, query.getSettleDate());
+        }
+        if (StringUtils.hasText(query.getSettleDateFrom())) {
+            criteria.andGreaterThanOrEqualTo(SettleTaskRelaHistory::getSettleDate, query.getSettleDateFrom());
+        }
+        if (StringUtils.hasText(query.getSettleDateTo())) {
+            criteria.andLessThanOrEqualTo(SettleTaskRelaHistory::getSettleDate, query.getSettleDateTo());
+        }
+        if (Objects.nonNull(query.getSettleResult())) {
+            criteria.andEqualTo(SettleTaskRelaHistory::getSettleResult, query.getSettleResult());
+        }
+        return settleTaskRelaHistoryMapper.selectByExample(weekend);
+    }
 }

+ 138 - 0
src/main/java/com/punchsettle/server/service/manager/impl/StatManagerImpl.java

@@ -1,5 +1,7 @@
 package com.punchsettle.server.service.manager.impl;
 
+import java.math.BigDecimal;
+import java.math.RoundingMode;
 import java.time.LocalDate;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -13,19 +15,34 @@ import java.util.stream.Collectors;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.cache.annotation.Cacheable;
 import org.springframework.stereotype.Component;
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.CollectionUtils;
 
+import com.punchsettle.server.atomic.IStatPiTaskService;
+import com.punchsettle.server.atomic.StatPiTask;
+import com.punchsettle.server.atomic.entity.PiTask;
 import com.punchsettle.server.atomic.entity.PiTaskHistory;
+import com.punchsettle.server.atomic.entity.SettleTaskRelaHistory;
 import com.punchsettle.server.atomic.entity.StatNewUser;
+import com.punchsettle.server.atomic.entity.StatPiTaskMonth;
+import com.punchsettle.server.atomic.entity.StatPiTaskWeek;
+import com.punchsettle.server.atomic.entity.StatPiTaskYear;
 import com.punchsettle.server.atomic.entity.StatPoints;
 import com.punchsettle.server.atomic.service.IPiTaskHistoryService;
+import com.punchsettle.server.atomic.service.IPiTaskService;
+import com.punchsettle.server.atomic.service.ISettleTaskRelaHistoryService;
 import com.punchsettle.server.atomic.service.IStatNewUserService;
+import com.punchsettle.server.atomic.service.IStatPiTaskWeekService;
 import com.punchsettle.server.atomic.service.IStatPointsService;
 import com.punchsettle.server.constant.CacheNameConstant;
 import com.punchsettle.server.constant.PunchInResultEnum;
+import com.punchsettle.server.constant.SettleResultEnum;
+import com.punchsettle.server.constant.StatPeriodEnum;
 import com.punchsettle.server.core.config.BizProperties;
 import com.punchsettle.server.pojo.punchIn.PiTaskHistoryQuery;
+import com.punchsettle.server.pojo.settle.SettleTaskRelaHistoryQuery;
 import com.punchsettle.server.pojo.stat.StatNewUserQuery;
+import com.punchsettle.server.pojo.stat.StatPiTaskQuery;
 import com.punchsettle.server.pojo.stat.StatPointsQuery;
 import com.punchsettle.server.pojo.ucharts.LineSeriesVO;
 import com.punchsettle.server.pojo.ucharts.LineVO;
@@ -42,6 +59,11 @@ import com.punchsettle.server.utiis.UserUtils;
 @Component
 public class StatManagerImpl implements IStatManager {
 
+    /**
+     * 数值100
+     */
+    private static final BigDecimal ONE_HUNDRED = BigDecimal.valueOf(100);
+
     @Autowired
     private IStatPointsService statPointsService;
 
@@ -54,6 +76,15 @@ public class StatManagerImpl implements IStatManager {
     @Autowired
     private BizProperties bizProperties;
 
+    @Autowired
+    private IStatPiTaskWeekService statPiTaskWeekService;
+
+    @Autowired
+    private ISettleTaskRelaHistoryService settleTaskRelaHistoryService;
+
+    @Autowired
+    private IPiTaskService piTaskService;
+
     @Override
     @Cacheable(cacheNames = CacheNameConstant.STAT_POINTS_LINE, key = "T(com.punchsettle.server.utiis.UserUtils).getCurrentUserId()")
     public LineVO queryStatPointsLine() {
@@ -197,4 +228,111 @@ public class StatManagerImpl implements IStatManager {
         lineVO.setSeries(Arrays.asList(totalTaskCountLineSeriesVO, punchInTaskCountLineSeriesVO, doneTaskCountLineSeriesVO));
         return lineVO;
     }
+
+    @Override
+    @Transactional(rollbackFor = Exception.class)
+    public void statPiTaskData(IStatPiTaskService statPiTaskService, StatPeriodEnum statPeriod, List<Long> userIds, LocalDate statTime, LocalDate statFirstDay, LocalDate statLastDay) {
+        // 查询任务数据
+        List<PiTask> piTasks = piTaskService.getActiveTask(userIds);
+        // 没有待统计任务跳过
+        if (CollectionUtils.isEmpty(piTasks)) {
+            return;
+        }
+
+        StatPiTaskQuery statPiTaskQuery = new StatPiTaskQuery();
+        statPiTaskQuery.setStatTime(statTime.toString());
+        statPiTaskQuery.setUserIds(userIds);
+        List<StatPiTask> statPiTaskDatas = statPiTaskService.queryByCondition(statPiTaskQuery);
+        // 任务唯一ID - 周统计数据
+        Map<Long, StatPiTask> statPiTaskDataMap = statPiTaskDatas.stream().collect(Collectors.toMap(StatPiTask::getTaskUniqueId, Function.identity(), (key1, key2) -> key1));
+
+        // 查询已结算数据
+        SettleTaskRelaHistoryQuery settleTaskRelaHistoryQuery = new SettleTaskRelaHistoryQuery();
+        settleTaskRelaHistoryQuery.setUserIds(userIds);
+        settleTaskRelaHistoryQuery.setSettleDateFrom(statFirstDay.toString());
+        settleTaskRelaHistoryQuery.setSettleDateTo(statLastDay.toString());
+        settleTaskRelaHistoryQuery.setSettleResult(SettleResultEnum.SETTLE);
+        List<SettleTaskRelaHistory> settleTaskRelaHistorieList = settleTaskRelaHistoryService.queryByCondition(settleTaskRelaHistoryQuery);
+        // 任务唯一ID - 结算任务关联记录
+        Map<Long, List<SettleTaskRelaHistory>> settleTaskRelaHistoryMap = settleTaskRelaHistorieList.stream().collect(Collectors.groupingBy(SettleTaskRelaHistory::getPiTaskUniqueId));
+
+        // 新增
+        List<StatPiTask> addStatPiTaskWeekList = new ArrayList<>();
+        // 更新
+        List<StatPiTask> updateStatPiTaskWeekList = new ArrayList<>();
+
+        for (PiTask piTask : piTasks) {
+            // 获取结算数据
+            List<SettleTaskRelaHistory> settleTaskRelaHistories = settleTaskRelaHistoryMap.get(piTask.getUniqueId());
+            // 统计数据
+            StatPiTask newStatPiTask = statPiTaskData(statPeriod, settleTaskRelaHistories);
+            // 获取统计数据
+            StatPiTask oldStatPiTaskWeek = statPiTaskDataMap.get(piTask.getUniqueId());
+
+            // 如果没有统计数据,则创建
+            if (Objects.isNull(oldStatPiTaskWeek)) {
+                newStatPiTask.setUserId(piTask.getCreatedBy());
+                newStatPiTask.setTaskUniqueId(piTask.getUniqueId());
+                newStatPiTask.setStatTime(statTime.toString());
+                addStatPiTaskWeekList.add(newStatPiTask);
+            } else {
+                newStatPiTask.setId(oldStatPiTaskWeek.getId());
+                updateStatPiTaskWeekList.add(newStatPiTask);
+            }
+        }
+
+        if (!CollectionUtils.isEmpty(addStatPiTaskWeekList)) {
+            statPiTaskWeekService.insertList(addStatPiTaskWeekList);
+        }
+
+        if (!CollectionUtils.isEmpty(updateStatPiTaskWeekList)) {
+            statPiTaskWeekService.batchUpdate(updateStatPiTaskWeekList);
+        }
+    }
+
+    /**
+     * 重新统计打卡任务数据,如果不存在结算记录,则所有数据为0
+     * @param statPeriod 统计周期
+     * @param settleTaskRelaHistories 结算记录
+     * @return
+     */
+    private StatPiTask statPiTaskData(StatPeriodEnum statPeriod, List<SettleTaskRelaHistory> settleTaskRelaHistories) {
+        List<SettleTaskRelaHistory> list = CollectionUtils.isEmpty(settleTaskRelaHistories) ? List.of() : settleTaskRelaHistories.stream().filter(v -> SettleResultEnum.SETTLE.equals(v.getSettleResult())).toList();
+        // 总需打卡数
+        int punchInTotalCount = list.size();
+        // 打卡数
+        int punchInCount = (int) list.stream().filter(v -> Objects.nonNull(v.getPiTaskHistoryId())).count();
+        // 打卡完成数
+        int punchInDoneCount = (int) list.stream().filter(v -> Optional.ofNullable(v.getSettlePoints()).orElse(0) > 0).count();
+        // 总结算积分
+        Integer settlePoints = list.stream().map(v -> Optional.ofNullable(v.getSettlePoints()).orElse(0)).reduce(0, Integer::sum);
+
+        // 打卡率
+        BigDecimal punchInRate = BigDecimal.ZERO;
+        // 打卡完成率
+        BigDecimal punchInDoneRate = BigDecimal.ZERO;
+        if (punchInTotalCount != 0) {
+            BigDecimal punchInTotalCountVal = BigDecimal.valueOf(punchInTotalCount);
+            punchInRate = BigDecimal.valueOf(punchInCount).divide(punchInTotalCountVal, 4, RoundingMode.HALF_UP).multiply(ONE_HUNDRED);
+            punchInDoneRate = BigDecimal.valueOf(punchInDoneCount).divide(punchInTotalCountVal, 4, RoundingMode.HALF_UP).multiply(ONE_HUNDRED);
+        }
+
+        StatPiTask statPiTask = null;
+        if (StatPeriodEnum.WEEK.equals(statPeriod)) {
+            statPiTask = new StatPiTaskWeek();
+        } else if (StatPeriodEnum.MONTH.equals(statPeriod)) {
+            statPiTask = new StatPiTaskMonth();
+        } else if (StatPeriodEnum.YEAR.equals(statPeriod)) {
+            statPiTask = new StatPiTaskYear();
+        }
+
+        statPiTask.setPunchInTotalCount(punchInTotalCount);
+        statPiTask.setPunchInCount(punchInCount);
+        statPiTask.setPunchInDoneCount(punchInDoneCount);
+        statPiTask.setPunchInRate(punchInRate);
+        statPiTask.setPunchInDoneRate(punchInDoneRate);
+        statPiTask.setPoints(settlePoints);
+        return statPiTask;
+    }
+
 }

+ 76 - 0
src/main/java/com/punchsettle/server/task/StatPiTask.java

@@ -0,0 +1,76 @@
+package com.punchsettle.server.task;
+
+import java.time.LocalDate;
+import java.util.List;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.util.CollectionUtils;
+
+import com.google.common.collect.Lists;
+import com.punchsettle.server.atomic.service.IStatPiTaskMonthService;
+import com.punchsettle.server.atomic.service.IStatPiTaskWeekService;
+import com.punchsettle.server.atomic.service.IStatPiTaskYearService;
+import com.punchsettle.server.atomic.service.IUserService;
+import com.punchsettle.server.constant.StatPeriodEnum;
+import com.punchsettle.server.service.manager.IStatManager;
+import com.punchsettle.server.utiis.DateUtils;
+
+import lombok.extern.slf4j.Slf4j;
+
+/**
+ * @author tyuio
+ * @version 1.0.0
+ * @date 2025/5/6 20:14
+ * @description 打卡任务统计(周,月,年) 定时任务
+ */
+@Slf4j
+@Component
+public class StatPiTask {
+
+    @Autowired
+    private IUserService userService;
+
+    @Autowired
+    private IStatPiTaskWeekService statPiTaskWeekService;
+
+    @Autowired
+    private IStatPiTaskMonthService statPiTaskMonthService;
+
+    @Autowired
+    private IStatPiTaskYearService statPiTaskYearService;
+
+    @Autowired
+    private IStatManager statManager;
+
+    public void execute() {
+        log.info("========== 打卡任务数据统计定时任务 开始执行 ==========");
+
+        List<Long> userIds = userService.listId();
+        if (CollectionUtils.isEmpty(userIds)) {
+            log.info("========== 打卡任务数据统计定时任务,没有待统计用户 结束执行 ==========");
+            return;
+        }
+
+        // 打卡日期
+        LocalDate statTime = LocalDate.now().minusDays(1);
+        // 周日
+        LocalDate firstDayOfWeek = DateUtils.getFirstDayOfWeek(statTime);
+        // 周日
+        LocalDate lastDayOfWeek = DateUtils.getLastDayOfWeek(statTime);
+
+        for (List<Long> tempUserIds : Lists.partition(userIds, 20)) {
+            try {
+                statManager.statPiTaskData(statPiTaskWeekService, StatPeriodEnum.WEEK, tempUserIds, statTime, firstDayOfWeek, lastDayOfWeek);
+                statManager.statPiTaskData(statPiTaskMonthService, StatPeriodEnum.MONTH, tempUserIds, statTime, firstDayOfWeek, lastDayOfWeek);
+                statManager.statPiTaskData(statPiTaskYearService, StatPeriodEnum.YEAR, tempUserIds, statTime, firstDayOfWeek, lastDayOfWeek);
+            } catch (Exception e) {
+                log.error("打卡任务数据统计定时任务执行异常", e);
+            }
+            // TODO 中间需打卡的变动次数可以考虑在编辑时进行校正
+        }
+
+
+        log.info("========== 打卡任务数据统计定时任务 开始执行 ==========");
+    }
+}