소스 검색

【feat】【v3】
1.新增枚举类

1.增加节假日接口
2.增加打卡判断逻辑

ChenYL 9 달 전
부모
커밋
a48da29f5f

+ 3 - 9
README.md

@@ -12,12 +12,6 @@
 
 
 
-## 待办列表
-
-* ~~对接前端~~
-* certbot自动续期
-* ~~结算任务增加定时任务自动执行~~
-* ~~数据库脚本审计字段(creation_time、last_update_time)增加默认值~~
-* ~~功能开发~~
-* ~~表设计~~
-* ~~需求文档编写~~
+## 参考
+
+* [SpringBoot节假日(OneAPI和天聚数行)](https://blog.csdn.net/m0_55841258/article/details/145198829)

+ 12 - 4
src/main/java/com/punchsettle/server/atomic/entity/PunchInMultiTask.java

@@ -6,6 +6,10 @@ import java.math.BigDecimal;
 
 import com.punchsettle.server.common.pojo.BaseEntity;
 
+import com.punchsettle.server.constant.ArchiveStatusEnum;
+import com.punchsettle.server.constant.CommonStatusEnum;
+import com.punchsettle.server.constant.ExtraMethodEnum;
+import com.punchsettle.server.constant.PunchInMethodMultiEnum;
 import jakarta.persistence.Column;
 import jakarta.persistence.Table;
 import lombok.Data;
@@ -33,9 +37,10 @@ public class PunchInMultiTask extends BaseEntity implements Serializable {
 
     /**
      * 任务状态(活跃-ACTIVE,归档-ARCHIVE)
+     * @see ArchiveStatusEnum
      */
     @Column(name = "multi_task_status")
-    private String multiTaskStatus;
+    private ArchiveStatusEnum multiTaskStatus;
 
     /**
      * 任务修改版本
@@ -51,9 +56,10 @@ public class PunchInMultiTask extends BaseEntity implements Serializable {
 
     /**
      * 打卡方式(次数-COUNT,比率-RATE)
+     * @see PunchInMethodMultiEnum
      */
     @Column(name = "punch_in_method")
-    private String punchInMethod;
+    private PunchInMethodMultiEnum punchInMethod;
 
     /**
      * 打卡完成次数
@@ -75,9 +81,10 @@ public class PunchInMultiTask extends BaseEntity implements Serializable {
 
     /**
      * 是否启用宽限期(ENABLED-启用,DISABLED-关闭)
+     * @see CommonStatusEnum
      */
     @Column(name = "grace_status")
-    private String graceStatus;
+    private CommonStatusEnum graceStatus;
 
     /**
      * 宽限期(单位:天)
@@ -99,9 +106,10 @@ public class PunchInMultiTask extends BaseEntity implements Serializable {
 
     /**
      * 额外奖励方式(无-NONE,固定-FIXED,区间-INTERVAL)
+     * @see ExtraMethodEnum
      */
     @Column(name = "extra_method")
-    private String extraMethod;
+    private ExtraMethodEnum extraMethod;
 
     /**
      * 奖励的积分(额外)

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

@@ -0,0 +1,23 @@
+package com.punchsettle.server.constant;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+
+/**
+ * @author myou
+ * @version 1.0.0
+ * @date 2025/4/13 8:58
+ * @description 多任务打卡方式枚举(次数-COUNT,比率-RATE)
+ */
+@Getter
+@AllArgsConstructor
+public enum PunchInMethodMultiEnum {
+
+    COUNT("次数"),
+    RATE("比率");
+
+    /**
+     * 名称
+     */
+    private String name;
+}

+ 22 - 0
src/main/java/com/punchsettle/server/feign/OneApiFeign.java

@@ -0,0 +1,22 @@
+package com.punchsettle.server.feign;
+
+import com.punchsettle.server.feign.dto.HolidayQuery;
+import com.punchsettle.server.feign.dto.OneApiResponse;
+import org.springframework.cloud.openfeign.FeignClient;
+
+/**
+ * @author myou
+ * @version 1.0.0
+ * @date 2025/4/13 10:30
+ * @description one-api接口平台
+ */
+@FeignClient(name = "one-api", url = "${one-api.url}")
+public interface OneApiFeign {
+
+    /**
+     * 查询节假日信息
+     * @param query
+     * @return
+     */
+    OneApiResponse queryHoliday(HolidayQuery query);
+}

+ 54 - 0
src/main/java/com/punchsettle/server/feign/dto/HolidayData.java

@@ -0,0 +1,54 @@
+package com.punchsettle.server.feign.dto;
+
+import lombok.Data;
+
+/**
+ * @author myou
+ * @version 1.0.0
+ * @date 2025/4/13 10:33
+ * @description 节假日数据
+ */
+@Data
+public class HolidayData {
+
+    /**
+     * 日期,格式为”yyyy-MM-dd“
+     */
+    private String date;
+
+    /**
+     * 农历日期,格式为”yyyy-MM-dd“
+     */
+    private String lunarDate;
+
+    /**
+     * 星期几,1-7,1代表星期一,7代表星期日
+     */
+    private Integer weekDay;
+
+    /**
+     * 状态:1-上班, 2-放假
+     * 上班:含正常工作日及补班;放假:含周末及节假日。
+     */
+    private Integer status;
+
+    /**
+     * 节日,国家法定节日:元旦节, 春节, 清明节, 劳动节, 端午节, 中秋节, 国庆节
+     */
+    private String festival;
+
+    /**
+     * 是否补班:1补班。需要补班,真是难受的一天!仅当需要补班时有该字段。
+     */
+    private Integer badDay;
+
+    /**
+     * 描述,表示什么时候补班,例如劳动节前补班、国庆节后补班等。仅需要补班时有该字段
+     */
+    private String description;
+
+    /**
+     * 是否法定节假日:1-是。如果是法定节假日则返回1,仅当是法定节假日时有该字段。
+     */
+    private Integer statutory;
+}

+ 24 - 0
src/main/java/com/punchsettle/server/feign/dto/HolidayQuery.java

@@ -0,0 +1,24 @@
+package com.punchsettle.server.feign.dto;
+
+import lombok.Data;
+
+/**
+ * @author myou
+ * @version 1.0.0
+ * @date 2025/4/13 10:33
+ * @description 节假日查询类
+ */
+@Data
+public class HolidayQuery {
+
+    /**
+     * 要查询的日期
+     * 可按年或月查询,支持前缀模糊匹配。如查询2023年则填写2023,查询2023年5月则填写2023-05
+     */
+    private String date;
+
+    /**
+     * 查询类型(1-仅节日,只返回节日和补班的日期;2-日历,返回每一天的。默认为1)
+     */
+    private Integer queryType;
+}

+ 30 - 0
src/main/java/com/punchsettle/server/feign/dto/OneApiResponse.java

@@ -0,0 +1,30 @@
+package com.punchsettle.server.feign.dto;
+
+import lombok.Data;
+
+import java.io.Serializable;
+
+/**
+ * @author myou
+ * @version 1.0.0
+ * @date 2025/4/13 10:33
+ * @description 节假日响应
+ */
+@Data
+public class OneApiResponse<T> implements Serializable {
+
+    /**
+     * 响应码
+     */
+    private Integer code;
+
+    /**
+     * 响应信息
+     */
+    private String msg;
+
+    /**
+     * 响应数据
+     */
+    private T data;
+}

+ 31 - 3
src/main/java/com/punchsettle/server/service/manager/IPunchInManager.java

@@ -2,10 +2,12 @@ package com.punchsettle.server.service.manager;
 
 import java.util.List;
 
-import com.punchsettle.server.atomic.entity.PunchIn;
-import com.punchsettle.server.atomic.entity.PunchInStatus;
+import com.punchsettle.server.atomic.entity.PunchInMultiTask;
+import com.punchsettle.server.atomic.entity.PunchInMultiTaskHistory;
 import com.punchsettle.server.atomic.entity.PunchInTask;
+import com.punchsettle.server.atomic.entity.PunchInTaskExt;
 import com.punchsettle.server.atomic.entity.PunchInTaskHistory;
+import com.punchsettle.server.constant.CommonStatusEnum;
 import com.punchsettle.server.constant.PunchInStatusEnum;
 import com.punchsettle.server.pojo.punchin.PunchInDataQuery;
 import com.punchsettle.server.pojo.punchin.PunchInDataVO;
@@ -76,6 +78,14 @@ public interface IPunchInManager {
      */
     PunchInDataVO queryPunchInData(PunchInDataQuery query);
 
+    /**
+     * 判断指定日期是否在打卡任务的重复周期内
+     * @param punchInTask 打卡任务
+     * @param repeatDateStr 指定日期
+     * @return true-在周期内,false-不在周期内
+     */
+    boolean judgeRepeat(PunchInTask punchInTask, String repeatDateStr);
+
     /**
      * 判断打卡状态
      * @param punchInTask 当前打卡任务
@@ -83,5 +93,23 @@ public interface IPunchInManager {
      * @param holidayFlag 是否是节假日(是-true,否-false)
      * @return
      */
-    PunchInStatusEnum judgePunchInStatus(PunchInTask punchInTask, PunchInTaskHistory punchInTaskHistory, boolean holidayFlag);
+    PunchInStatusEnum judgePunchInStatusInTask(PunchInTask punchInTask, PunchInTaskHistory punchInTaskHistory, boolean holidayFlag);
+
+    /**
+     * 判断打卡状态(多任务)
+     * @param punchInMultiTask 打卡多任务任务
+     * @param punchInTaskHistoryList 打卡记录
+     * @param multiTaskNum 参与多任务计算数量
+     * @return
+     */
+    PunchInStatusEnum judgePunchInStatusInMultiTask(PunchInMultiTask punchInMultiTask, List<PunchInTaskHistory> punchInTaskHistoryList, int multiTaskNum);
+
+    /**
+     * 计算积分
+     * @param punchInTask 打卡任务
+     * @param punchInTaskExt 打卡任务拓展信息
+     * @param punchInTaskHistory 打卡记录
+     * @return
+     */
+    int calculatePointsInTask(PunchInTask punchInTask, PunchInTaskExt punchInTaskExt, PunchInTaskHistory punchInTaskHistory);
 }

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

@@ -3,6 +3,7 @@ package com.punchsettle.server.service.manager.impl;
 import java.math.BigDecimal;
 import java.math.RoundingMode;
 import java.text.SimpleDateFormat;
+import java.time.DayOfWeek;
 import java.time.LocalDate;
 import java.time.LocalTime;
 import java.time.YearMonth;
@@ -16,6 +17,10 @@ import java.util.Optional;
 import java.util.function.Function;
 import java.util.stream.Collectors;
 
+import com.punchsettle.server.atomic.entity.PunchInMultiTask;
+import com.punchsettle.server.atomic.entity.PunchInTaskExt;
+import com.punchsettle.server.constant.PunchInMethodMultiEnum;
+import com.punchsettle.server.constant.RepeatCategoryEnum;
 import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -56,6 +61,7 @@ import com.punchsettle.server.utiis.DateUtils;
 import com.punchsettle.server.utiis.UserUtils;
 
 import lombok.extern.slf4j.Slf4j;
+import org.springframework.util.StringUtils;
 
 /**
  * @author tyuio
@@ -436,8 +442,48 @@ public class PunchInManagerImpl implements IPunchInManager {
         return punchInDataVO;
     }
 
+    /**
+     * 判断是否是节假日
+     * @param date
+     * @return true:是节假日,false:不是节假日
+     */
+    private boolean judgeHoliday(String date) {
+        return false;
+    }
+
     @Override
-    public PunchInStatusEnum judgePunchInStatus(PunchInTask punchInTask, PunchInTaskHistory punchInTaskHistory, boolean holidayFlag) {
+    public boolean judgeRepeat(PunchInTask punchInTask, String repeatDateStr) {
+        // 每天
+        if (RepeatCategoryEnum.EVERYDAY.equals(punchInTask.getRepeatCategory())) {
+            return true;
+        }
+
+        // 法定工作日
+        if (RepeatCategoryEnum.WORKDAY.equals(punchInTask.getRepeatCategory())) {
+            return !judgeHoliday(repeatDateStr);
+        }
+
+        // 法定节假日(含周末)
+        if (RepeatCategoryEnum.HOLIDAY.equals(punchInTask.getRepeatCategory())) {
+            return !judgeHoliday(repeatDateStr);
+        }
+
+        // 自定义
+        if (RepeatCategoryEnum.CUSTOM.equals(punchInTask.getRepeatCategory())) {
+            if (!StringUtils.hasText(punchInTask.getRepeatCustomDay())) {
+                BusinessException.throwFail(String.format("打卡任务ID:%s, 重复周期类型:自定义重复,没有设定自定义重复日期"));
+            }
+
+            LocalDate repeatDate = LocalDate.parse(repeatDateStr);
+            int dayOfWeekValue = repeatDate.getDayOfWeek().getValue();
+            return punchInTask.getRepeatCustomDay().contains(String.valueOf(dayOfWeekValue));
+        }
+
+        return false;
+    }
+
+    @Override
+    public PunchInStatusEnum judgePunchInStatusInTask(PunchInTask punchInTask, PunchInTaskHistory punchInTaskHistory, boolean holidayFlag) {
         Assert.isNullInBusiness(punchInTask, "打卡任务不能为空 ");
         // 没有打卡记录,直接没完成
         if (Objects.isNull(punchInTaskHistory)) {
@@ -456,33 +502,89 @@ public class PunchInManagerImpl implements IPunchInManager {
 
         // 计数打卡,要区分是否节假日使用不同的判断标准
         if (PunchInMethodEnum.COUNT.equals(punchInTask.getPunchInMethod())) {
-            
-            int countTrackTarget = Optional.ofNullable(enableHolidayFlag ? punchInTask.getHolidayCountTrack() : punchInTask.getCountTrack()).orElse(0);
-            int countTrack = Optional.ofNullable(punchInTaskHistory.getCountTrack()).orElse(0);
-            if (CompareRuleEnum.GTE.equals(punchInTask.getCompareRule()) && )
-            if (PunchInRuleEnum.GREATER_OR_EQUAL.equals(punchIn.getRule()) && recordCountTrack.compareTo(punchIn.getCountTrack()) == -1) {
-                return PunchInStatusV1Enum.UN_FINISH;
+            int countTrack = enableHolidayFlag ? punchInTask.getHolidayCountTrack() : punchInTask.getCountTrack();
+            int punchInCountTrack = Optional.ofNullable(punchInTaskHistory.getCountTrack()).orElse(0);
+            if (CompareRuleEnum.GTE.equals(punchInTask.getCompareRule()) && punchInCountTrack >= countTrack) {
+                return PunchInStatusEnum.DONE;
             }
-            if (PunchInRuleEnum.LESS_OR_EQUAL.equals(punchIn.getRule()) && recordCountTrack.compareTo(punchIn.getCountTrack()) == 1) {
-                return PunchInStatusV1Enum.UN_FINISH;
+            if (CompareRuleEnum.LTE.equals(punchInTask.getCompareRule()) && punchInCountTrack <= countTrack) {
+                return PunchInStatusEnum.DONE;
             }
-
-            return PunchInStatusV1Enum.FINISH;
+            return PunchInStatusEnum.UNDONE;
         }
 
         // 计时打卡,要区分是否节假日使用不同的判断标准
-        if (PunchInCategoryEnum.TIME.equals(punchIn.getCategory())) {
-            LocalTime recordTimeTrack = Optional.ofNullable(punchInRecord.getTimeTrack()).orElse(LocalTime.parse("00:00:00.000"));
-            if (PunchInRuleEnum.GREATER_OR_EQUAL.equals(punchIn.getRule()) && recordTimeTrack.compareTo(punchIn.getTimeTrack()) == -1) {
-                return PunchInStatusV1Enum.UN_FINISH;
+        if (PunchInCategoryEnum.TIME.equals(punchInTask.getPunchInMethod())) {
+            LocalTime timeTrack = enableHolidayFlag ? punchInTask.getHolidayTimeTrack() : punchInTask.getTimeTrack();
+            LocalTime punchInTimeTrack = Optional.ofNullable(punchInTaskHistory.getTimeTrack()).orElse(LocalTime.parse("00:00:00.000"));
+            if (CompareRuleEnum.GTE.equals(punchInTask.getCompareRule()) && punchInTimeTrack.compareTo(timeTrack) > -1) {
+                return PunchInStatusEnum.DONE;
             }
-            if (PunchInRuleEnum.LESS_OR_EQUAL.equals(punchIn.getRule()) && recordTimeTrack.compareTo(punchIn.getTimeTrack()) == 1) {
-                return PunchInStatusV1Enum.UN_FINISH;
+            if (CompareRuleEnum.LTE.equals(punchInTask.getCompareRule()) && punchInTimeTrack.compareTo(timeTrack) < 1) {
+                return PunchInStatusEnum.DONE;
             }
 
-            return PunchInStatusV1Enum.FINISH;
+            return PunchInStatusEnum.UNDONE;
         }
 
         return PunchInStatusEnum.UNDONE;
     }
+
+    /**
+     * 默认打卡完成率
+     */
+    private static final BigDecimal DEFAULT_PUNCH_IN_DONE_RATE = new BigDecimal("101.00");
+
+    @Override
+    public PunchInStatusEnum judgePunchInStatusInMultiTask(PunchInMultiTask punchInMultiTask, List<PunchInTaskHistory> punchInTaskHistoryList, int multiTaskNum) {
+        if (CollectionUtils.isEmpty(punchInTaskHistoryList) || multiTaskNum == 0) {
+            return PunchInStatusEnum.UNDONE;
+        }
+
+        // 完成的打卡数量
+        long punchInDoneCount = punchInTaskHistoryList.stream().filter(v -> PunchInStatusEnum.DONE.equals(v.getPunchInStatus())).count();
+
+        // 次数,当天打卡次数大于等于设置的次数,则完成打卡
+        if (PunchInMethodMultiEnum.COUNT.equals(punchInMultiTask.getPunchInMethod())) {
+            // 没有设置时默认设置一个较大的数,避免出现打卡次数为0的情况
+            Integer doneCount = Optional.ofNullable(punchInMultiTask.getPunchInDoneCount()).orElse(punchInTaskHistoryList.size() + 1);
+            return punchInDoneCount >= doneCount ? PunchInStatusEnum.DONE : PunchInStatusEnum.UNDONE;
+        }
+
+        // 比率,当天打卡完成比率大于等于设置的比率,则完成打卡
+
+        if (PunchInMethodMultiEnum.RATE.equals(punchInMultiTask.getPunchInMethod())) {
+            // 没有设置时默认设置一个较大的数,避免出现打卡完成率为0的情况
+            BigDecimal doneRate = Optional.ofNullable(punchInMultiTask.getPunchInDoneRate()).orElse(DEFAULT_PUNCH_IN_DONE_RATE);
+            BigDecimal punchInDoneRate = BigDecimal.valueOf(punchInDoneCount).divide(BigDecimal.valueOf(multiTaskNum), 2, RoundingMode.HALF_UP);
+            return punchInDoneRate.compareTo(doneRate) > -1 ? PunchInStatusEnum.DONE : PunchInStatusEnum.UNDONE;
+        }
+
+        return PunchInStatusEnum.UNDONE;
+    }
+
+    @Override
+    public int calculatePointsInTask(PunchInTask punchInTask, PunchInTaskExt punchInTaskExt, PunchInTaskHistory punchInTaskHistory) {
+        // 未完成打卡,积分为0
+        if (PunchInStatusEnum.UNDONE.equals(punchInTaskHistory.getPunchInStatus())) {
+            return 0;
+        }
+
+        // 单个任务积分=基本积分+(可选)额外积分+(可选)连续完成额外积分+法定节假日(含周末)双倍奖励+全勤双倍奖励
+        int points = Optional.ofNullable(punchInTask.getPoints()).orElse(0);
+
+        // 启用了全勤奖励
+        if (CommonStatusEnum.ENABLED.equals(punchInTask.getFullAttendanceStatus())) {
+
+        }
+
+        // 启用了法定节假日(含周末)双倍奖励
+        if (CommonStatusEnum.ENABLED.equals(punchInTask.getHolidayStatus()) && judgeHoliday(punchInTaskHistory.getPunchInDate())) {
+            points *= 2;
+        }
+
+        return points;
+    }
+
+    // TODO 多任务结算
 }

+ 4 - 0
src/main/resources/application.yaml

@@ -15,3 +15,7 @@ jasypt:
     algorithm: PBEWithMD5AndDES
     salt-generator-classname: org.jasypt.salt.RandomSaltGenerator
     iv-generator-classname: org.jasypt.iv.RandomIvGenerator
+
+# one-api接口平台
+one-api:
+  url: https://oneapi.coderbox.cn/openapi/public/holiday