| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260 |
- package com.punchsettle.server.service.manager.impl;
- import java.time.LocalDate;
- import java.time.LocalTime;
- import java.util.Arrays;
- import java.util.List;
- import java.util.Objects;
- import java.util.Optional;
- import java.util.Set;
- import java.util.stream.Collectors;
- import com.punchsettle.server.atomic.entity.PiStatus;
- import com.punchsettle.server.constant.ContinueStageEnum;
- import com.punchsettle.server.utiis.DateUtils;
- import org.springframework.beans.factory.annotation.Autowired;
- import org.springframework.stereotype.Component;
- import org.springframework.util.CollectionUtils;
- import org.springframework.util.StringUtils;
- import com.punchsettle.server.atomic.entity.PiMultiTask;
- import com.punchsettle.server.atomic.entity.PiTask;
- import com.punchsettle.server.atomic.entity.PiTaskHistory;
- import com.punchsettle.server.common.constant.CommonEnableStatusEnum;
- import com.punchsettle.server.common.exception.BusinessException;
- import com.punchsettle.server.common.utils.Assert;
- import com.punchsettle.server.constant.CompareRuleEnum;
- import com.punchsettle.server.constant.PunchInMethodEnum;
- import com.punchsettle.server.constant.PunchInResultEnum;
- import com.punchsettle.server.constant.RepeatCategoryEnum;
- import com.punchsettle.server.service.manager.ICalendarManager;
- import com.punchsettle.server.service.manager.IPunchInManager;
- import lombok.extern.slf4j.Slf4j;
- /**
- * @author tyuio
- * @version 1.0.0
- * @date 2025/4/15 14:10
- * @description 打卡服务类
- */
- @Slf4j
- @Component
- public class PunchInManagerImpl implements IPunchInManager {
- @Autowired
- private ICalendarManager calendarManager;
- @Override
- public boolean judgeRepeat(PiTask piTask, String repeatDateStr) {
- // 每天
- if (RepeatCategoryEnum.EVERYDAY.equals(piTask.getRepeatCategory())) {
- return true;
- }
- // 法定工作日
- if (RepeatCategoryEnum.WORKDAY.equals(piTask.getRepeatCategory())) {
- return !calendarManager.judgeHoliday(repeatDateStr);
- }
- // 法定节假日(含周末)
- if (RepeatCategoryEnum.HOLIDAY.equals(piTask.getRepeatCategory())) {
- return !calendarManager.judgeHoliday(repeatDateStr);
- }
- // 自定义
- if (RepeatCategoryEnum.CUSTOM.equals(piTask.getRepeatCategory())) {
- if (!StringUtils.hasText(piTask.getRepeatCustomDay())) {
- BusinessException.throwFail(String.format("打卡任务ID:%s, 重复周期类型:自定义重复,没有设定自定义重复日期"));
- }
- LocalDate repeatDate = LocalDate.parse(repeatDateStr);
- int dayOfWeekValue = repeatDate.getDayOfWeek().getValue();
- return piTask.getRepeatCustomDay().contains(String.valueOf(dayOfWeekValue));
- }
- return false;
- }
- @Override
- public PunchInResultEnum judgePunchInResultInTask(PiTask piTask, PiTaskHistory piTaskHistory) {
- Assert.isNullInBusiness(piTask, "打卡任务不能为空 ");
- // 没有打卡记录,直接没完成
- if (Objects.isNull(piTaskHistory)) {
- return PunchInResultEnum.UNDONE;
- }
- // 单次打卡,不区分是否节假日
- if (PunchInMethodEnum.SINGLE.equals(piTask.getPunchInMethod())) {
- int countTrack = Optional.ofNullable(piTask.getCountTrack()).orElse(0);
- return countTrack > 0 ? PunchInResultEnum.DONE : PunchInResultEnum.UNDONE;
- }
- // 打卡任务的节假日启用配置
- CommonEnableStatusEnum holidayStatus = Optional.ofNullable(piTask.getHolidayStatus()).orElse(CommonEnableStatusEnum.DISABLED);
- boolean enableHolidayFlag = CommonEnableStatusEnum.ENABLED.equals(holidayStatus) && calendarManager.judgeHoliday(piTaskHistory.getPunchInDate());
- // 计数打卡,要区分是否节假日使用不同的判断标准
- if (PunchInMethodEnum.COUNT.equals(piTask.getPunchInMethod())) {
- int countTrack = enableHolidayFlag ? piTask.getHolidayCountTrack() : piTask.getCountTrack();
- int punchInCountTrack = Optional.ofNullable(piTaskHistory.getCountTrack()).orElse(0);
- if (CompareRuleEnum.GTE.equals(piTask.getCompareRule()) && punchInCountTrack >= countTrack) {
- return PunchInResultEnum.DONE;
- }
- if (CompareRuleEnum.LTE.equals(piTask.getCompareRule()) && punchInCountTrack <= countTrack) {
- return PunchInResultEnum.DONE;
- }
- return PunchInResultEnum.UNDONE;
- }
- // 计时打卡,要区分是否节假日使用不同的判断标准
- if (PunchInMethodEnum.TIMING.equals(piTask.getPunchInMethod())) {
- LocalTime timeTrack = enableHolidayFlag ? piTask.getHolidayTimeTrack() : piTask.getTimeTrack();
- LocalTime punchInTimeTrack = Optional.ofNullable(piTaskHistory.getTimeTrack()).orElse(LocalTime.parse("00:00:00.000"));
- if (CompareRuleEnum.GTE.equals(piTask.getCompareRule()) && punchInTimeTrack.compareTo(timeTrack) > -1) {
- return PunchInResultEnum.DONE;
- }
- if (CompareRuleEnum.LTE.equals(piTask.getCompareRule()) && punchInTimeTrack.compareTo(timeTrack) < 1) {
- return PunchInResultEnum.DONE;
- }
- return PunchInResultEnum.UNDONE;
- }
- return PunchInResultEnum.UNDONE;
- }
- @Override
- public PunchInResultEnum judgePunchInResultInMultiTask(PiMultiTask piMultiTask, List<PiTaskHistory> piTaskHistoryList) {
- if (CollectionUtils.isEmpty(piTaskHistoryList)) {
- return PunchInResultEnum.UNDONE;
- }
- // 完成的打卡数量
- long punchInDoneCount = piTaskHistoryList.stream().filter(v -> PunchInResultEnum.DONE.equals(v.getPunchInResult())).count();
- // 当天打卡次数大于等于设置的次数,则完成打卡
- // 没有设置时默认设置一个较大的数,避免出现打卡次数为0的情况
- Integer doneCount = Optional.ofNullable(piMultiTask.getPunchInDoneCount()).orElse(piTaskHistoryList.size() + 1);
- return punchInDoneCount >= doneCount ? PunchInResultEnum.DONE : PunchInResultEnum.UNDONE;
- }
- @Override
- public int getPunchInTotalCountInWeek(PiTask piTask, String specifiedDateStr) {
- Assert.isNullInBusiness(piTask, "打卡任务不能为空 ");
- Assert.isNull(specifiedDateStr, "指定日期不能为空 ");
- if (RepeatCategoryEnum.EVERYDAY.equals(piTask.getRepeatCategory())) {
- return 7;
- }
- if (RepeatCategoryEnum.CUSTOM.equals(piTask.getRepeatCategory())) {
- return piTask.getRepeatCustomDay().split(",").length;
- }
- // 指定日期
- LocalDate specifiedDate = LocalDate.parse(specifiedDateStr);
- if (RepeatCategoryEnum.WORKDAY.equals(piTask.getRepeatCategory())) {
- List<LocalDate> dateRange = DateUtils.getDateRangeInWeek(specifiedDate);
- return (int) dateRange.stream().map(v -> DateUtils.YYYY_MM_DD_FORMATTER.format(v))
- .filter(v -> calendarManager.judgeWorkday(v)).count();
- }
- if (RepeatCategoryEnum.HOLIDAY.equals(piTask.getRepeatCategory())) {
- List<LocalDate> dateRange = DateUtils.getDateRangeInWeek(specifiedDate);
- return (int) dateRange.stream().map(v -> DateUtils.YYYY_MM_DD_FORMATTER.format(v))
- .filter(v -> calendarManager.judgeHoliday(v)).count();
- }
- return 0;
- }
- @Override
- public int getPunchInTotalCountInMonth(PiTask piTask, String specifiedDateStr) {
- Assert.isNullInBusiness(piTask, "打卡任务不能为空 ");
- Assert.isNull(specifiedDateStr, "指定日期不能为空 ");
- // 指定日期
- LocalDate specifiedDate = LocalDate.parse(specifiedDateStr);
- if (RepeatCategoryEnum.EVERYDAY.equals(piTask.getRepeatCategory())) {
- return specifiedDate.lengthOfMonth();
- }
- // 日期列表
- List<LocalDate> dateRange = DateUtils.getDateRangeInMonth(specifiedDate);
- if (RepeatCategoryEnum.CUSTOM.equals(piTask.getRepeatCategory())) {
- String[] split = piTask.getRepeatCustomDay().split(",");
- Set<Integer> customDays = Arrays.stream(split).map(v -> Integer.valueOf(v)).collect(Collectors.toSet());
- return (int) dateRange.stream().map(v -> v.getDayOfWeek().getValue()).filter(customDays::contains).count();
- }
- if (RepeatCategoryEnum.WORKDAY.equals(piTask.getRepeatCategory())) {
- return (int) dateRange.stream().map(v -> DateUtils.YYYY_MM_DD_FORMATTER.format(v))
- .filter(v -> calendarManager.judgeWorkday(v)).count();
- }
- if (RepeatCategoryEnum.HOLIDAY.equals(piTask.getRepeatCategory())) {
- return (int) dateRange.stream().map(v -> DateUtils.YYYY_MM_DD_FORMATTER.format(v))
- .filter(v -> calendarManager.judgeHoliday(v)).count();
- }
- return 0;
- }
- @Override
- public ContinueStageEnum judgeContinueStageInTask(PiTask piTask, PiTaskHistory piTaskHistory, PiStatus piStatus, LocalDate punchInDate) {
- if (CommonEnableStatusEnum.DISABLED.equals(piTask.getContinueStatus())) {
- return ContinueStageEnum.NONE;
- }
- // TODO 启用/关闭连续打卡规则时要对状态表进行数据初始化
- // 宽限期
- if (ContinueStageEnum.GRACE_STAGE.equals(piStatus.getContinueStage())) {
- LocalDate graceDay = piStatus.getStageStartDate().plusDays(piTask.getGraceDay());
- // 仍处于宽限期限内
- if (punchInDate.compareTo(graceDay) <= 0) {
- return ContinueStageEnum.GRACE_STAGE;
- }
- // 已超过宽限期限,但是未完成打卡
- if (PunchInResultEnum.UNDONE.equals(piTaskHistory.getPunchInResult())) {
- return ContinueStageEnum.GRACE_STAGE;
- }
- // 已超过宽限期限,且已完成打卡,进入正常打卡期
- return ContinueStageEnum.NORMAL_STAGE;
- }
- // 正常打卡期
- if (ContinueStageEnum.NORMAL_STAGE.equals(piStatus.getContinueStage())) {
- // 完成打卡则继续是正常打卡期,否则是惩罚期
- if (PunchInResultEnum.DONE.equals(piTaskHistory.getPunchInResult())) {
- return ContinueStageEnum.NORMAL_STAGE;
- }
- // 连续中断次数大于等于设置的中断次数,重新进入宽限期
- if (piStatus.getContinueInterruptedCount() + 1 > piTask.getContinueInterruptedCount()) {
- return ContinueStageEnum.GRACE_STAGE;
- }
- return ContinueStageEnum.PENALTY_STAGE;
- }
- // 惩罚期
- if (ContinueStageEnum.PENALTY_STAGE.equals(piStatus.getContinueStage())) {
- // 仍处于惩罚期
- if (punchInDate.compareTo(piStatus.getStageEndDate()) <= 0) {
- return ContinueStageEnum.GRACE_STAGE;
- }
- return ContinueStageEnum.NORMAL_STAGE;
- }
- return ContinueStageEnum.NONE;
- }
- }
|