|
|
@@ -1,226 +1,644 @@
|
|
|
package com.punchsettle.server.service.manager.impl;
|
|
|
|
|
|
+import java.math.BigDecimal;
|
|
|
+import java.math.RoundingMode;
|
|
|
+import java.text.SimpleDateFormat;
|
|
|
import java.time.LocalDate;
|
|
|
import java.time.LocalTime;
|
|
|
+import java.time.YearMonth;
|
|
|
import java.time.temporal.ChronoUnit;
|
|
|
+import java.util.ArrayList;
|
|
|
import java.util.Arrays;
|
|
|
+import java.util.Comparator;
|
|
|
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.atomic.ContinueTask;
|
|
|
-import com.punchsettle.server.atomic.entity.PiStatus;
|
|
|
-import com.punchsettle.server.constant.ContinueStageEnum;
|
|
|
-import com.punchsettle.server.utiis.DateUtils;
|
|
|
+import org.springframework.beans.BeanUtils;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
-import org.springframework.stereotype.Component;
|
|
|
+import org.springframework.stereotype.Service;
|
|
|
+import org.springframework.transaction.annotation.Transactional;
|
|
|
import org.springframework.util.CollectionUtils;
|
|
|
import org.springframework.util.StringUtils;
|
|
|
|
|
|
-import com.punchsettle.server.atomic.entity.PiMultiTask;
|
|
|
+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.PunchIn;
|
|
|
+import com.punchsettle.server.atomic.entity.PunchInRecord;
|
|
|
+import com.punchsettle.server.atomic.service.IPiTaskHistoryService;
|
|
|
+import com.punchsettle.server.atomic.service.IPiTaskService;
|
|
|
+import com.punchsettle.server.atomic.service.IPunchInRecordService;
|
|
|
+import com.punchsettle.server.atomic.service.IPunchInService;
|
|
|
+import com.punchsettle.server.atomic.service.IStatPiTaskMonthService;
|
|
|
+import com.punchsettle.server.atomic.service.IStatPiTaskYearService;
|
|
|
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.ArchiveStatusEnum;
|
|
|
+import com.punchsettle.server.constant.PunchInExtraMethodEnum;
|
|
|
import com.punchsettle.server.constant.PunchInMethodEnum;
|
|
|
import com.punchsettle.server.constant.PunchInResultEnum;
|
|
|
+import com.punchsettle.server.constant.PunchInResultViewEnum;
|
|
|
+import com.punchsettle.server.constant.PunchInSettleTypeEnum;
|
|
|
+import com.punchsettle.server.constant.PunchInStatusV1Enum;
|
|
|
+import com.punchsettle.server.constant.PunchInTaskStatusEnum;
|
|
|
import com.punchsettle.server.constant.RepeatCategoryEnum;
|
|
|
-import com.punchsettle.server.service.manager.ICalendarManager;
|
|
|
+import com.punchsettle.server.constant.StatPeriodEnum;
|
|
|
+import com.punchsettle.server.pojo.punchIn.PiTaskHistoryQuery;
|
|
|
+import com.punchsettle.server.pojo.punchIn.PiTaskHistorySimpleVO;
|
|
|
+import com.punchsettle.server.pojo.punchIn.PiTaskHistoryStatVO;
|
|
|
+import com.punchsettle.server.pojo.punchIn.PiTaskQuery;
|
|
|
+import com.punchsettle.server.pojo.punchIn.PiTaskRequest;
|
|
|
+import com.punchsettle.server.pojo.punchIn.PiTaskSimpleVO;
|
|
|
+import com.punchsettle.server.pojo.punchIn.PiTaskStatQuery;
|
|
|
+import com.punchsettle.server.pojo.punchIn.PiTaskStatVO;
|
|
|
+import com.punchsettle.server.pojo.punchIn.PiTaskToDoVO;
|
|
|
+import com.punchsettle.server.pojo.punchIn.PiTaskVO;
|
|
|
+import com.punchsettle.server.pojo.punchIn.PunchInRequest;
|
|
|
+import com.punchsettle.server.pojo.punchinV1.PunchInCalendarDataVO;
|
|
|
+import com.punchsettle.server.pojo.punchinV1.PunchInDataQuery;
|
|
|
+import com.punchsettle.server.pojo.punchinV1.PunchInDataVO;
|
|
|
+import com.punchsettle.server.pojo.punchinV1.PunchInRecordDataVO;
|
|
|
+import com.punchsettle.server.pojo.punchinV1.PunchInRecordQuery;
|
|
|
+import com.punchsettle.server.pojo.punchinV1.PunchInRecordRequest;
|
|
|
+import com.punchsettle.server.service.manager.IPunchInCoreManager;
|
|
|
import com.punchsettle.server.service.manager.IPunchInManager;
|
|
|
+import com.punchsettle.server.service.manager.ISettleManagerV1;
|
|
|
+import com.punchsettle.server.utiis.DateUtils;
|
|
|
+import com.punchsettle.server.utiis.UserUtils;
|
|
|
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
|
/**
|
|
|
* @author tyuio
|
|
|
* @version 1.0.0
|
|
|
- * @date 2025/4/15 14:10
|
|
|
- * @description 打卡服务类
|
|
|
+ * @description 打卡结算任务 服务类
|
|
|
+ * @date 2024/11/25 15:12
|
|
|
*/
|
|
|
@Slf4j
|
|
|
-@Component
|
|
|
+@Service
|
|
|
public class PunchInManagerImpl implements IPunchInManager {
|
|
|
|
|
|
@Autowired
|
|
|
- private ICalendarManager calendarManager;
|
|
|
+ private IPunchInService punchInService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IPunchInRecordService punchInRecordService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private ISettleManagerV1 settleManager;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IPiTaskService piTaskService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IPiTaskHistoryService piTaskHistoryService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IPunchInCoreManager punchInCoreManager;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IStatPiTaskYearService statPiTaskYearService;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private IStatPiTaskMonthService statPiTaskMonthService;
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 默认显示时间00:00:00.000
|
|
|
+ */
|
|
|
+ private static final LocalTime DEFAULT_DISPLAY_TIME = LocalTime.parse("00:00:00.000");
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 数值100
|
|
|
+ */
|
|
|
+ private static final BigDecimal ONE_HUNDRED = new BigDecimal(100);
|
|
|
|
|
|
@Override
|
|
|
- public boolean judgeRepeat(PiTask piTask, String repeatDateStr) {
|
|
|
- // 每天
|
|
|
- if (RepeatCategoryEnum.EVERYDAY.equals(piTask.getRepeatCategory())) {
|
|
|
- return true;
|
|
|
+ public List<PiTaskToDoVO> queryToDoList(Long currentUserId) {
|
|
|
+ Assert.isNull(currentUserId);
|
|
|
+ // 查询打卡任务
|
|
|
+ PiTaskQuery piTaskQuery = new PiTaskQuery();
|
|
|
+ piTaskQuery.setArchiveStatus(ArchiveStatusEnum.ACTIVE);
|
|
|
+ piTaskQuery.setTaskStatus(PunchInTaskStatusEnum.ACTIVE);
|
|
|
+ piTaskQuery.setUserIds(Arrays.asList(currentUserId));
|
|
|
+ List<PiTask> piTasks = piTaskService.queryByCondition(piTaskQuery);
|
|
|
+
|
|
|
+ if (CollectionUtils.isEmpty(piTasks)) {
|
|
|
+ return List.of();
|
|
|
}
|
|
|
|
|
|
- // 法定工作日
|
|
|
- if (RepeatCategoryEnum.WORKDAY.equals(piTask.getRepeatCategory())) {
|
|
|
- return calendarManager.judgeWorkday(repeatDateStr);
|
|
|
- }
|
|
|
+ // 当前日期
|
|
|
+ LocalDate today = LocalDate.now();
|
|
|
+ String todayStr = DateUtils.YYYY_MM_DD_FORMATTER.format(today);
|
|
|
+ // 当前时间
|
|
|
+ LocalTime nowTime = LocalTime.now();
|
|
|
+ // 打卡任务唯一ID
|
|
|
+ Set<Long> taskUniqueIds = piTasks.stream().map(PiTask::getUniqueId).collect(Collectors.toSet());
|
|
|
+
|
|
|
+ // 查询打卡记录
|
|
|
+ PiTaskHistoryQuery piTaskHistoryQuery = new PiTaskHistoryQuery();
|
|
|
+ piTaskHistoryQuery.setPunchInDate(todayStr);
|
|
|
+ piTaskHistoryQuery.setTaskUniqueIds(taskUniqueIds);
|
|
|
+ piTaskHistoryQuery.setUserIds(Arrays.asList(currentUserId));
|
|
|
+ List<PiTaskHistory> piTaskHistories = piTaskHistoryService.queryByCondition(piTaskHistoryQuery);
|
|
|
+ // 打卡任务唯一ID-打卡记录关联
|
|
|
+ Map<Long, PiTaskHistory> piTaskHistoryMap = piTaskHistories.stream().collect(Collectors.toMap(PiTaskHistory::getTaskUniqueId, Function.identity(), (key1, key2) -> key1));
|
|
|
+
|
|
|
+ // 1.判断重复频率,只显示今天待打卡的任务
|
|
|
+ // 2.判断显示时间,还没到点显示的暂时不显示
|
|
|
+ // 3.根据displayOrder进行排序,按自然顺序排列
|
|
|
+ return piTasks.stream().filter(piTask -> punchInCoreManager.judgeRepeat(piTask, todayStr))
|
|
|
+ .filter(piTask -> {
|
|
|
+ LocalTime displayTime = Optional.ofNullable(piTask.getDisplayTime()).orElse(DEFAULT_DISPLAY_TIME);
|
|
|
+ return nowTime.compareTo(displayTime) > -1;
|
|
|
+ })
|
|
|
+ .sorted(Comparator.comparing(piTask -> Optional.ofNullable(piTask.getDisplayOrder()).orElse(0)))
|
|
|
+ .map(piTask -> {
|
|
|
+ PiTaskToDoVO piTaskToDoVO = new PiTaskToDoVO();
|
|
|
+ BeanUtils.copyProperties(piTask, piTaskToDoVO);
|
|
|
+ // 获取并设置已打卡记录
|
|
|
+ PiTaskHistory piTaskHistory = piTaskHistoryMap.get(piTask.getUniqueId());
|
|
|
+ if (Objects.nonNull(piTaskHistory)) {
|
|
|
+ piTaskToDoVO.setCurrentCountTrack(piTaskHistory.getCountTrack());
|
|
|
+ piTaskToDoVO.setCurrentTimeTrack(piTaskHistory.getTimeTrack());
|
|
|
+ }
|
|
|
+ return piTaskToDoVO;
|
|
|
+ }).collect(Collectors.toList());
|
|
|
+ }
|
|
|
|
|
|
- // 法定节假日(含周末)
|
|
|
- if (RepeatCategoryEnum.HOLIDAY.equals(piTask.getRepeatCategory())) {
|
|
|
- return calendarManager.judgeHoliday(repeatDateStr);
|
|
|
+ @Override
|
|
|
+ public List<PiTaskSimpleVO> queryTaskList(Long currentUserId) {
|
|
|
+ Assert.isNull(currentUserId);
|
|
|
+ // 查询打卡任务
|
|
|
+ PiTaskQuery piTaskQuery = new PiTaskQuery();
|
|
|
+ piTaskQuery.setArchiveStatus(ArchiveStatusEnum.ACTIVE);
|
|
|
+ piTaskQuery.setTaskStatus(PunchInTaskStatusEnum.ACTIVE);
|
|
|
+ piTaskQuery.setUserIds(Arrays.asList(currentUserId));
|
|
|
+ List<PiTask> piTasks = piTaskService.queryByCondition(piTaskQuery);
|
|
|
+
|
|
|
+ if (CollectionUtils.isEmpty(piTasks)) {
|
|
|
+ return List.of();
|
|
|
}
|
|
|
|
|
|
- // 自定义
|
|
|
- if (RepeatCategoryEnum.CUSTOM.equals(piTask.getRepeatCategory())) {
|
|
|
- if (!StringUtils.hasText(piTask.getRepeatCustomDay())) {
|
|
|
- BusinessException.throwFail(String.format("打卡任务ID:%s, 重复周期类型:自定义重复,没有设定自定义重复日期"));
|
|
|
- }
|
|
|
+ // 当前日期
|
|
|
+ LocalDate today = LocalDate.now();
|
|
|
+ String todayStr = DateUtils.YYYY_MM_DD_FORMATTER.format(today);
|
|
|
+ // 获取一周的起始日期范围
|
|
|
+ List<LocalDate> weeklyDateRange = DateUtils.getDateRangeInWeek();
|
|
|
+
|
|
|
+ // 打卡任务唯一ID
|
|
|
+ Set<Long> taskUniqueIds = piTasks.stream().map(PiTask::getUniqueId).collect(Collectors.toSet());
|
|
|
+
|
|
|
+ // 找出范围内的打卡记录
|
|
|
+ PiTaskHistoryQuery piTaskHistoryQuery = new PiTaskHistoryQuery();
|
|
|
+ piTaskHistoryQuery.setTaskUniqueIds(taskUniqueIds);
|
|
|
+ piTaskHistoryQuery.setUserIds(Arrays.asList(currentUserId));
|
|
|
+ piTaskHistoryQuery.setPunchInDateFrom(weeklyDateRange.getFirst().toString());
|
|
|
+ piTaskHistoryQuery.setPunchInDateTo(weeklyDateRange.getLast().toString());
|
|
|
+ List<PiTaskHistory> piTaskHistories = piTaskHistoryService.queryByCondition(piTaskHistoryQuery);
|
|
|
+ // 打卡任务唯一ID-打卡记录关联
|
|
|
+ Map<Long, List<PiTaskHistory>> piTaskHistoryMap = piTaskHistories.stream().collect(Collectors.groupingBy(PiTaskHistory::getTaskUniqueId));
|
|
|
+
|
|
|
+ // 按顺序排列
|
|
|
+ return piTasks.stream()
|
|
|
+ .sorted(Comparator.comparing(piTask -> Optional.ofNullable(piTask.getDisplayOrder()).orElse(0)))
|
|
|
+ .map(piTask -> {
|
|
|
+ PiTaskSimpleVO piTaskSimpleVO = new PiTaskSimpleVO();
|
|
|
+ BeanUtils.copyProperties(piTask, piTaskSimpleVO);
|
|
|
+ // 获取对应的打卡记录
|
|
|
+ List<PiTaskHistory> tempPiTaskHistories = Optional.ofNullable(piTaskHistoryMap.get(piTask.getUniqueId())).orElse(List.of());
|
|
|
+ // 任务创建日期
|
|
|
+ LocalDate creationDate = piTask.getCreationTime().toLocalDateTime().toLocalDate();
|
|
|
+ // 打卡日期-打卡记录关联
|
|
|
+ Map<String, PiTaskHistory> tempPiTaskHistoryMap = tempPiTaskHistories.stream().collect(Collectors.toMap(PiTaskHistory::getPunchInDate, Function.identity(), (key1, key2) -> key1));
|
|
|
+ // 按时间范围遍历,构造页面打卡结果
|
|
|
+ List<PiTaskHistorySimpleVO> piTaskHistorySimpleVOS = weeklyDateRange.stream().map(punchInDate -> {
|
|
|
+ // 打卡日期
|
|
|
+ String punchInDateStr = punchInDate.toString();
|
|
|
+
|
|
|
+ // 判断页面打卡结果
|
|
|
+ PiTaskHistory piTaskHistory = tempPiTaskHistoryMap.get(punchInDateStr);
|
|
|
+ PunchInResultViewEnum punchInResultView = judgePunchInResultView(piTask, piTaskHistory, punchInDate, today, creationDate);
|
|
|
+
|
|
|
+ // 构建页面打卡结果
|
|
|
+ PiTaskHistorySimpleVO piTaskHistorySimpleVO = new PiTaskHistorySimpleVO();
|
|
|
+ piTaskHistorySimpleVO.setPunchInDate(punchInDateStr);
|
|
|
+ piTaskHistorySimpleVO.setPunchInResult(punchInResultView);
|
|
|
+ return piTaskHistorySimpleVO;
|
|
|
+ }).collect(Collectors.toList());
|
|
|
+ piTaskSimpleVO.setPiTaskHistorySimpleVOS(piTaskHistorySimpleVOS);
|
|
|
+
|
|
|
+ return piTaskSimpleVO;
|
|
|
+ }).collect(Collectors.toList());
|
|
|
+ }
|
|
|
|
|
|
- LocalDate repeatDate = LocalDate.parse(repeatDateStr);
|
|
|
- int dayOfWeekValue = repeatDate.getDayOfWeek().getValue();
|
|
|
- return piTask.getRepeatCustomDay().contains(String.valueOf(dayOfWeekValue));
|
|
|
+ /**
|
|
|
+ * 判断页面打卡结果
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private PunchInResultViewEnum judgePunchInResultView(PiTask piTask, PiTaskHistory piTaskHistory, LocalDate punchInDate, LocalDate today, LocalDate creationDate) {
|
|
|
+ // 未到打卡时间
|
|
|
+ if (punchInDate.isAfter(today)) {
|
|
|
+ return PunchInResultViewEnum.FUTURE;
|
|
|
}
|
|
|
|
|
|
- return false;
|
|
|
- }
|
|
|
+ // 任务未创建,不需要打卡
|
|
|
+ if (punchInDate.isBefore(creationDate)) {
|
|
|
+ return PunchInResultViewEnum.NOT_NEED;
|
|
|
+ }
|
|
|
|
|
|
- @Override
|
|
|
- public PunchInResultEnum judgePunchInResultInTask(PiTask piTask, PiTaskHistory piTaskHistory) {
|
|
|
- Assert.isNullInBusiness(piTask, "打卡任务不能为空 ");
|
|
|
+ // 打卡日期在今天之前且存在打卡记录,则简单判断打卡结果即可
|
|
|
+ if (punchInDate.isBefore(today) && Objects.nonNull(piTaskHistory)) {
|
|
|
+ return PunchInResultEnum.DONE.equals(piTaskHistory.getPunchInResult()) ? PunchInResultViewEnum.DONE : PunchInResultViewEnum.UNDONE;
|
|
|
+ }
|
|
|
|
|
|
- // 没有打卡记录,直接没完成
|
|
|
- if (Objects.isNull(piTaskHistory)) {
|
|
|
- return PunchInResultEnum.UNDONE;
|
|
|
+ // 打卡日期在今天之前且不存在打卡记录,则有两种情况:1.那天不用打卡;2.那天需要打卡但是没打卡
|
|
|
+ // TODO 这里应该要有打卡任务的每天记录才能精准判断,现在先简化一下用当前任务的重复频率进行判断
|
|
|
+ if (punchInDate.isBefore(today) && Objects.isNull(piTaskHistory)) {
|
|
|
+ // 判断是否需要打卡
|
|
|
+ boolean repeatResult = punchInCoreManager.judgeRepeat(piTask, today.toString());
|
|
|
+ return repeatResult ? PunchInResultViewEnum.UNDONE : PunchInResultViewEnum.NOT_NEED;
|
|
|
}
|
|
|
|
|
|
- // 单次打卡,不区分是否节假日
|
|
|
- if (PunchInMethodEnum.SINGLE.equals(piTask.getPunchInMethod())) {
|
|
|
- int countTrack = Optional.ofNullable(piTaskHistory.getCountTrack()).orElse(0);
|
|
|
- return countTrack > 0 ? PunchInResultEnum.DONE : PunchInResultEnum.UNDONE;
|
|
|
+ // 打卡日期是今天,且不存在打卡记录,则有两种情况:1.今天不用打卡;2.今天需要打卡但是还没打卡
|
|
|
+ if (punchInDate.isEqual(today) && Objects.isNull(piTaskHistory)) {
|
|
|
+ // 判断是否需要打卡
|
|
|
+ boolean repeatResult = punchInCoreManager.judgeRepeat(piTask, today.toString());
|
|
|
+ return repeatResult ? PunchInResultViewEnum.UNDONE : PunchInResultViewEnum.NOT_NEED;
|
|
|
}
|
|
|
|
|
|
- // 打卡任务的节假日启用配置
|
|
|
- CommonEnableStatusEnum holidayStatus = Optional.ofNullable(piTask.getHolidayStatus()).orElse(CommonEnableStatusEnum.DISABLED);
|
|
|
- boolean enableHolidayFlag = CommonEnableStatusEnum.ENABLED.equals(holidayStatus) && calendarManager.judgeHoliday(piTaskHistory.getPunchInDate());
|
|
|
+ // 打卡日期是今天,且存在打卡记录,则进一步判断打卡结果
|
|
|
+ if (punchInDate.isEqual(today) && Objects.nonNull(piTaskHistory)) {
|
|
|
+ PunchInResultEnum punchInResult = punchInCoreManager.judgePunchInResultInTask(piTask, piTaskHistory);
|
|
|
+ return PunchInResultEnum.DONE.equals(punchInResult) ? PunchInResultViewEnum.DONE : PunchInResultViewEnum.UNDONE;
|
|
|
+ }
|
|
|
|
|
|
- // 计数打卡,要区分是否节假日使用不同的判断标准
|
|
|
- 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;
|
|
|
+ // 不符合任何情况则是未打卡
|
|
|
+ return PunchInResultViewEnum.NOT_NEED;
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public PiTaskVO queryTask(Long id) {
|
|
|
+ Assert.isNullInBusiness(id, "请传入待查询的任务ID");
|
|
|
+ return Optional.ofNullable(piTaskService.getById(id)).map(piTask -> {
|
|
|
+ PiTaskVO piTaskVO = new PiTaskVO();
|
|
|
+ BeanUtils.copyProperties(piTask, piTaskVO);
|
|
|
+ return piTaskVO;
|
|
|
+ }).orElseThrow(() -> BusinessException.fail("无法查询到该打卡任务"));
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public void saveTask(PiTaskRequest request) {
|
|
|
+ Assert.isNullInBusiness(request, "请传入任务信息");
|
|
|
+
|
|
|
+ // 数据校验
|
|
|
+ if (PunchInMethodEnum.TIMING.equals(request.getPunchInMethod())) {
|
|
|
+ if (Objects.isNull(request.getCompareRule()) || Objects.isNull(request.getTimeTrack())) {
|
|
|
+ throw BusinessException.fail("打卡类型:计时,比较规则和时间不能为空");
|
|
|
}
|
|
|
- if (CompareRuleEnum.LTE.equals(piTask.getCompareRule()) && punchInCountTrack <= countTrack) {
|
|
|
- return PunchInResultEnum.DONE;
|
|
|
+ if (CommonEnableStatusEnum.ENABLED.equals(request.getHolidayStatus()) && Objects.isNull(request.getHolidayTimeTrack())) {
|
|
|
+ throw BusinessException.fail("打卡类型:计时,启用了节假日奖励,节假日的时间不能为空");
|
|
|
}
|
|
|
- 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 (PunchInMethodEnum.COUNT.equals(request.getPunchInMethod())) {
|
|
|
+ if (Objects.isNull(request.getCompareRule()) || Objects.isNull(request.getCountTrack())) {
|
|
|
+ throw BusinessException.fail("打卡类型:计数,比较规则和次数不能为空");
|
|
|
+ }
|
|
|
+ if (CommonEnableStatusEnum.ENABLED.equals(request.getHolidayStatus()) && Objects.isNull(request.getHolidayCountTrack())) {
|
|
|
+ throw BusinessException.fail("打卡类型:计数,启用了节假日奖励,节假日的次数不能为空");
|
|
|
+ }
|
|
|
+ }
|
|
|
+ if (CommonEnableStatusEnum.ENABLED.equals(request.getFullAttendanceStatus()) && (Objects.isNull(request.getFullAttendancePeriod()) || Objects.isNull(request.getFullAttendanceFaultToleranceCnt()))) {
|
|
|
+ throw BusinessException.fail("启用了全勤奖励,全勤周期和全勤容错次数不能为空");
|
|
|
+ }
|
|
|
+ if (RepeatCategoryEnum.CUSTOM.equals(request.getRepeatCategory()) && !StringUtils.hasText(request.getRepeatCustomDay())) {
|
|
|
+ throw BusinessException.fail("自定义重复周期,自定义重复日不能为空");
|
|
|
+ }
|
|
|
+ if (PunchInExtraMethodEnum.FIXED.equals(request.getExtraMethod()) || PunchInExtraMethodEnum.INTERVAL.equals(request.getExtraMethod())) {
|
|
|
+ if (PunchInMethodEnum.TIMING.equals(request.getPunchInMethod()) && Objects.isNull(request.getExtraTimeStep())) {
|
|
|
+ throw BusinessException.fail("打卡类型:计时,额外奖励方式为固定或区间,额外奖励时间间隔不能为空");
|
|
|
+ }
|
|
|
+ if (PunchInExtraMethodEnum.FIXED.equals(request.getExtraMethod()) && Objects.isNull(request.getExtraPoints())) {
|
|
|
+ throw BusinessException.fail("额外奖励方式为固定,额外奖励积分不能为空");
|
|
|
}
|
|
|
- if (CompareRuleEnum.LTE.equals(piTask.getCompareRule()) && punchInTimeTrack.compareTo(timeTrack) < 1) {
|
|
|
- return PunchInResultEnum.DONE;
|
|
|
+ if (PunchInExtraMethodEnum.INTERVAL.equals(request.getExtraMethod()) && CollectionUtils.isEmpty(request.getTaskExtList())) {
|
|
|
+ throw BusinessException.fail("额外奖励方式为区间,积分区间信息不能为空");
|
|
|
}
|
|
|
+ }
|
|
|
+ if (CommonEnableStatusEnum.ENABLED.equals(request.getContinueStatus()) && (Objects.isNull(request.getGraceDay()) || Objects.isNull(request.getContinueInterruptedCount()) || Objects.isNull(request.getPenaltyDay()))) {
|
|
|
+ throw BusinessException.fail("启用了连续规则,宽限期、连续中断次数、惩罚天数不能为空");
|
|
|
+ }
|
|
|
+ if (CommonEnableStatusEnum.ENABLED.equals(request.getTaskPointsStatus()) && CollectionUtils.isEmpty(request.getContinueTaskExtList())) {
|
|
|
+ throw BusinessException.fail("启用了任务积分计算,连续任务积分区间信息不能为空");
|
|
|
+ }
|
|
|
|
|
|
- return PunchInResultEnum.UNDONE;
|
|
|
+ // 新增打卡任务
|
|
|
+ PiTask addPiTask = new PiTask();
|
|
|
+ BeanUtils.copyProperties(request, addPiTask);
|
|
|
+ addPiTask.setId(null);
|
|
|
+ addPiTask.setTaskStatus(PunchInTaskStatusEnum.ACTIVE);
|
|
|
+ addPiTask.setTaskVersion(0);
|
|
|
+ addPiTask.setArchiveStatus(ArchiveStatusEnum.ACTIVE);
|
|
|
+
|
|
|
+ // 如果任务已存在,则更新任务版本号、设置唯一ID、旧数据归档
|
|
|
+ if (Objects.nonNull(request.getId())) {
|
|
|
+ PiTask piTask = Optional.ofNullable(piTaskService.getById(request.getId())).orElseThrow(() -> BusinessException.fail("无法查询到该打卡任务"));
|
|
|
+ addPiTask.setTaskVersion(piTask.getTaskVersion() + 1);
|
|
|
+ addPiTask.setUniqueId(piTask.getUniqueId());
|
|
|
+
|
|
|
+ // 旧数据归档
|
|
|
+ PiTask updatePiTask = new PiTask();
|
|
|
+ updatePiTask.setId(piTask.getId());
|
|
|
+ updatePiTask.setTaskStatus(PunchInTaskStatusEnum.ARCHIVE);
|
|
|
+ piTaskService.update(updatePiTask);
|
|
|
}
|
|
|
|
|
|
- return PunchInResultEnum.UNDONE;
|
|
|
+ // 保存数据
|
|
|
+ piTaskService.insert(addPiTask);
|
|
|
+ // 如果首次保存,需要设置唯一ID
|
|
|
+ if (Objects.isNull(addPiTask.getUniqueId())) {
|
|
|
+ PiTask updatePiTask = new PiTask();
|
|
|
+ updatePiTask.setId(addPiTask.getId());
|
|
|
+ updatePiTask.setUniqueId(addPiTask.getId());
|
|
|
+ piTaskService.update(updatePiTask);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public PunchInResultEnum judgePunchInResultInMultiTask(PiMultiTask piMultiTask, List<PiTaskHistory> piTaskHistoryList) {
|
|
|
- // 没有打卡记录 或者 没有启用多任务 则直接返回未完成
|
|
|
- if (CollectionUtils.isEmpty(piTaskHistoryList) || CommonEnableStatusEnum.DISABLED.equals(piMultiTask.getTaskPointsStatus())) {
|
|
|
- return PunchInResultEnum.UNDONE;
|
|
|
- }
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public void deleteTask(Long id) {
|
|
|
+ Assert.isNullInBusiness(id, "请传入待删除的任务");
|
|
|
|
|
|
- // 完成的打卡数量
|
|
|
- long punchInDoneCount = piTaskHistoryList.stream().filter(v -> PunchInResultEnum.DONE.equals(v.getPunchInResult())).count();
|
|
|
+ // 新增打卡任务记录
|
|
|
+ PiTask addPiTask = copyAndArchivePiTask(id);
|
|
|
+ addPiTask.setTaskStatus(PunchInTaskStatusEnum.DELETE);
|
|
|
|
|
|
- // 当天打卡次数大于等于设置的次数,则完成打卡
|
|
|
- // 没有设置时默认设置一个较大的数,避免出现打卡次数为0的情况
|
|
|
- Integer doneCount = Optional.ofNullable(piMultiTask.getPunchInDoneCount()).orElse(piTaskHistoryList.size() + 1);
|
|
|
- return punchInDoneCount >= doneCount ? PunchInResultEnum.DONE : PunchInResultEnum.UNDONE;
|
|
|
+ piTaskService.insert(addPiTask);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public int getPunchInTotalCountInRange(RepeatCategoryEnum repeatCategory, String repeatCustomDay, LocalDate repeatStartDate, LocalDate repeatEndDate) {
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public void doPunchIn(PunchInRequest request) {
|
|
|
+ if (Objects.isNull(request) || Objects.isNull(request.getId())) {
|
|
|
+ BusinessException.throwFail("请传入待打卡的任务");
|
|
|
+ }
|
|
|
|
|
|
- if (RepeatCategoryEnum.EVERYDAY.equals(repeatCategory)) {
|
|
|
- return (int) ChronoUnit.DAYS.between(repeatStartDate, repeatEndDate.plusDays(1));
|
|
|
+ PiTask piTask = Optional.ofNullable(piTaskService.getById(request.getId())).orElseThrow(() -> BusinessException.fail("无法查询到该打卡任务"));
|
|
|
+ if (PunchInMethodEnum.TIMING.equals(piTask.getPunchInMethod()) && Objects.isNull(request.getTimeTrack())) {
|
|
|
+ BusinessException.throwFail("打卡类型:计时,请传入时间记录");
|
|
|
}
|
|
|
|
|
|
- List<LocalDate> dateRange = DateUtils.getDateRange(repeatStartDate, repeatEndDate);
|
|
|
+ // 打卡日期
|
|
|
+ String punchInDate = LocalDate.now().toString();
|
|
|
+
|
|
|
+ // 查询今天的打卡记录
|
|
|
+ PiTaskHistory oldPiTaskHistory = piTaskHistoryService.getByTaskUniqueIdAndPunchInDate(piTask.getUniqueId(), punchInDate);
|
|
|
+
|
|
|
+ // 待更新/新增的打卡记录
|
|
|
+ PiTaskHistory tempPiTaskHistory = new PiTaskHistory();
|
|
|
+ // 不存在则新增,存在则更新
|
|
|
+ if (Objects.isNull(oldPiTaskHistory)) {
|
|
|
+ tempPiTaskHistory.setTaskUniqueId(piTask.getUniqueId());
|
|
|
+ tempPiTaskHistory.setPunchInDate(punchInDate);
|
|
|
+ tempPiTaskHistory.setUserId(UserUtils.getCurrentUserId());
|
|
|
+ } else {
|
|
|
+ tempPiTaskHistory.setId(oldPiTaskHistory.getId());
|
|
|
+ }
|
|
|
+
|
|
|
+ // 打卡类型:单次打卡,
|
|
|
+ if (PunchInMethodEnum.SINGLE.equals(piTask.getPunchInMethod())) {
|
|
|
+ // 需要判断是否重复打卡
|
|
|
+ if (Objects.nonNull(oldPiTaskHistory) && Optional.ofNullable(oldPiTaskHistory.getCountTrack()).orElse(0) > 0) {
|
|
|
+ BusinessException.throwFail("已打卡,无须重复打卡");
|
|
|
+ }
|
|
|
+ // 默认打卡次数是1,是计数打卡的特列
|
|
|
+ tempPiTaskHistory.setCountTrack(1);
|
|
|
+ }
|
|
|
|
|
|
- if (RepeatCategoryEnum.CUSTOM.equals(repeatCategory)) {
|
|
|
- String[] split = repeatCustomDay.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 (PunchInMethodEnum.COUNT.equals(piTask.getPunchInMethod())) {
|
|
|
+ tempPiTaskHistory.setCountTrack(Optional.ofNullable(oldPiTaskHistory.getCountTrack()).orElse(0) + 1);
|
|
|
}
|
|
|
|
|
|
- if (RepeatCategoryEnum.WORKDAY.equals(repeatCategory)) {
|
|
|
- return (int) dateRange.stream().map(v -> DateUtils.YYYY_MM_DD_FORMATTER.format(v))
|
|
|
- .filter(v -> calendarManager.judgeWorkday(v)).count();
|
|
|
+ // 打卡类型:计时,需要记录最新打卡时长
|
|
|
+ if (PunchInMethodEnum.TIMING.equals(piTask.getPunchInMethod())) {
|
|
|
+ tempPiTaskHistory.setTimeTrack(request.getTimeTrack());
|
|
|
}
|
|
|
|
|
|
- if (RepeatCategoryEnum.HOLIDAY.equals(repeatCategory)) {
|
|
|
- return (int) dateRange.stream().map(v -> DateUtils.YYYY_MM_DD_FORMATTER.format(v))
|
|
|
- .filter(v -> calendarManager.judgeHoliday(v)).count();
|
|
|
+ // 新增或更新
|
|
|
+ if (Objects.isNull(oldPiTaskHistory)) {
|
|
|
+ piTaskHistoryService.insert(tempPiTaskHistory);
|
|
|
+ } else {
|
|
|
+ piTaskHistoryService.update(tempPiTaskHistory);
|
|
|
}
|
|
|
+ }
|
|
|
|
|
|
- return 0;
|
|
|
+ @Override
|
|
|
+ @Transactional(rollbackFor = Exception.class)
|
|
|
+ public void archiveTask(Long id) {
|
|
|
+ Assert.isNullInBusiness(id, "请传入待删除的任务");
|
|
|
+
|
|
|
+ // 归档
|
|
|
+ PiTask addPiTask = copyAndArchivePiTask(id);
|
|
|
+ addPiTask.setArchiveStatus(ArchiveStatusEnum.ARCHIVE);
|
|
|
+ piTaskService.insert(addPiTask);
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
- public ContinueStageEnum judgeContinueStage(ContinueTask continueTask, PunchInResultEnum punchInResult, PiStatus piStatus, LocalDate punchInDate) {
|
|
|
- if (CommonEnableStatusEnum.DISABLED.equals(continueTask.getContinueStatus())) {
|
|
|
- return ContinueStageEnum.NONE;
|
|
|
+ public void remakePunchIn(PunchInRecordRequest request) {
|
|
|
+ // 待补卡的打卡日期
|
|
|
+ LocalDate punchInDate = LocalDate.parse(request.getPunchInDate());
|
|
|
+
|
|
|
+ // 如果补打卡日期是今天,则不允许补卡
|
|
|
+ if (punchInDate.isEqual(LocalDate.now())) {
|
|
|
+ BusinessException.throwFail("补打卡日期不能为今天");
|
|
|
}
|
|
|
|
|
|
- // TODO 启用/关闭连续打卡规则时要对状态表进行数据初始化
|
|
|
+ // 获取打卡任务
|
|
|
+ PunchIn punchIn = Optional.ofNullable(punchInService.getById(request.getPunchInId()))
|
|
|
+ .orElseThrow(() -> BusinessException.fail("无法查询到该打卡任务"));
|
|
|
+ // 补打卡的打卡日期不能早于打卡任务创建日期
|
|
|
+ if (punchInDate.isBefore(punchIn.getCreationTime().toLocalDateTime().toLocalDate())) {
|
|
|
+ BusinessException.throwFail("补打卡日期不能早于打卡任务创建日期");
|
|
|
+ }
|
|
|
|
|
|
- // 宽限期
|
|
|
- if (ContinueStageEnum.GRACE_STAGE.equals(piStatus.getContinueStage())) {
|
|
|
- LocalDate graceDay = piStatus.getStageStartDate().plusDays(continueTask.getGraceDay());
|
|
|
- // 仍处于宽限期限内
|
|
|
- if (punchInDate.compareTo(graceDay) <= 0) {
|
|
|
- return ContinueStageEnum.GRACE_STAGE;
|
|
|
- }
|
|
|
+ settleManager.settleHandler(PunchInSettleTypeEnum.REMAKE, punchInDate,
|
|
|
+ Arrays.asList(UserUtils.getCurrentUserId()), Arrays.asList(request.getPunchInId()));
|
|
|
+ }
|
|
|
|
|
|
- // 已超过宽限期限,但是未完成打卡
|
|
|
- if (PunchInResultEnum.UNDONE.equals(punchInResult)) {
|
|
|
- return ContinueStageEnum.GRACE_STAGE;
|
|
|
- }
|
|
|
+ @Override
|
|
|
+ public void revokePunchIn(Long id) {
|
|
|
+ // 获取打卡任务
|
|
|
+ PiTask piTask = Optional.ofNullable(piTaskService.getById(id)).orElseThrow(() -> BusinessException.fail("无法查询到该打卡任务"));
|
|
|
+ // 获取打卡记录
|
|
|
+ PiTaskHistory piTaskHistory = piTaskHistoryService.getByTaskUniqueIdAndPunchInDate(piTask.getUniqueId(), LocalDate.now().toString());
|
|
|
|
|
|
- // 已超过宽限期限,且已完成打卡,进入正常打卡期
|
|
|
- return ContinueStageEnum.NORMAL_STAGE;
|
|
|
+ if (Objects.isNull(piTaskHistory)) {
|
|
|
+ return;
|
|
|
}
|
|
|
|
|
|
- // 正常打卡期
|
|
|
- if (ContinueStageEnum.NORMAL_STAGE.equals(piStatus.getContinueStage())) {
|
|
|
- // 完成打卡则继续是正常打卡期,否则是惩罚期
|
|
|
- if (PunchInResultEnum.DONE.equals(punchInResult)) {
|
|
|
- return ContinueStageEnum.NORMAL_STAGE;
|
|
|
- }
|
|
|
+ PiTaskHistory updatePiTaskHistory = new PiTaskHistory();
|
|
|
+ updatePiTaskHistory.setId(piTaskHistory.getId());
|
|
|
+
|
|
|
+ // 单次打卡,次数置为0
|
|
|
+ if (PunchInMethodEnum.SINGLE.equals(piTask.getPunchInMethod())) {
|
|
|
+ updatePiTaskHistory.setCountTrack(0);
|
|
|
+ }
|
|
|
|
|
|
- // 连续中断次数大于等于设置的中断次数,重新进入宽限期,这里加1是因为需要加上本次的中断次数
|
|
|
- if (piStatus.getContinueInterruptedCount() + 1 > continueTask.getContinueInterruptedCount()) {
|
|
|
- return ContinueStageEnum.GRACE_STAGE;
|
|
|
+ // 计时打卡 时间置为00:00:00.000
|
|
|
+ if (PunchInMethodEnum.TIMING.equals(piTask.getPunchInMethod())) {
|
|
|
+ updatePiTaskHistory.setTimeTrack(DEFAULT_DISPLAY_TIME);
|
|
|
+ }
|
|
|
+
|
|
|
+ // 计数打卡,当前打卡次数减1
|
|
|
+ if (PunchInMethodEnum.COUNT.equals(piTask.getPunchInMethod())) {
|
|
|
+ Integer countTrack = Optional.ofNullable(piTaskHistory.getCountTrack()).orElse(0);
|
|
|
+ if (countTrack == 0) {
|
|
|
+ return;
|
|
|
}
|
|
|
+ updatePiTaskHistory.setCountTrack(countTrack - 1);
|
|
|
+ }
|
|
|
|
|
|
- return ContinueStageEnum.PENALTY_STAGE;
|
|
|
+ // 更新
|
|
|
+ piTaskHistoryService.update(updatePiTaskHistory);
|
|
|
+ }
|
|
|
+
|
|
|
+ @Override
|
|
|
+ public PiTaskStatVO queryStat(PiTaskStatQuery query) {
|
|
|
+ // 当前用户ID
|
|
|
+ Long currentUserId = UserUtils.getCurrentUserId();
|
|
|
+ // 查询统计数据
|
|
|
+ StatPiTask statPiTask = null;
|
|
|
+ if (StatPeriodEnum.YEAR.equals(query.getStatPeriod())) {
|
|
|
+ statPiTask = statPiTaskYearService.getByUserIdAndStatTime(currentUserId, query.getStatTime());
|
|
|
+ } else if (StatPeriodEnum.MONTH.equals(query.getStatPeriod())) {
|
|
|
+ statPiTask = statPiTaskMonthService.getByUserIdAndStatTime(currentUserId, query.getStatTime());
|
|
|
}
|
|
|
|
|
|
- // 惩罚期
|
|
|
- if (ContinueStageEnum.PENALTY_STAGE.equals(piStatus.getContinueStage())) {
|
|
|
- // 仍处于惩罚期
|
|
|
- if (punchInDate.compareTo(piStatus.getStageEndDate()) <= 0) {
|
|
|
- return ContinueStageEnum.PENALTY_STAGE;
|
|
|
+ if (Objects.isNull(statPiTask)) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 查询打卡记录
|
|
|
+ PiTaskHistoryQuery piTaskHistoryQuery = new PiTaskHistoryQuery();
|
|
|
+ piTaskHistoryQuery.setUserIds(Arrays.asList(currentUserId));
|
|
|
+ piTaskHistoryQuery.setPunchInDateLike(query.getStatTime());
|
|
|
+ List<PiTaskHistory> piTaskHistories = piTaskHistoryService.queryByCondition(piTaskHistoryQuery);
|
|
|
+
|
|
|
+ // 查询打卡任务
|
|
|
+ Set<Long> piTaskIds = piTaskHistories.stream().map(PiTaskHistory::getSettlePiTaskId).collect(Collectors.toSet());
|
|
|
+ PiTaskQuery piTaskQuery = new PiTaskQuery();
|
|
|
+ piTaskQuery.setIds(piTaskIds);
|
|
|
+ List<PiTask> piTasks = piTaskService.queryByCondition(piTaskQuery);
|
|
|
+ // 打卡任务ID-打卡任务对象关联
|
|
|
+ Map<Long, PiTask> piTaskMap = piTasks.stream().collect(Collectors.toMap(PiTask::getId, Function.identity(), (key1, key2) -> key1));
|
|
|
+
|
|
|
+ // 组装数据
|
|
|
+ List<PiTaskHistoryStatVO> piTaskHistoryStatVOS = piTaskHistories.stream().map(piTaskHistory -> {
|
|
|
+ PiTaskHistoryStatVO piTaskHistoryStatVO = new PiTaskHistoryStatVO();
|
|
|
+ BeanUtils.copyProperties(piTaskHistory, piTaskHistoryStatVO);
|
|
|
+ return piTaskHistoryStatVO;
|
|
|
+ }).collect(Collectors.toList());
|
|
|
+
|
|
|
+ PiTaskStatVO piTaskStatVO = new PiTaskStatVO();
|
|
|
+ BeanUtils.copyProperties(statPiTask, piTaskStatVO);
|
|
|
+ piTaskStatVO.setPiTaskHistoryStatVOS(piTaskHistoryStatVOS);
|
|
|
+ return piTaskStatVO;
|
|
|
+ }
|
|
|
+ @Override
|
|
|
+ public PunchInDataVO queryPunchInData(PunchInDataQuery query) {
|
|
|
+ PunchIn punchIn = Optional.ofNullable(punchInService.getById(query.getId()))
|
|
|
+ .orElseThrow(() -> BusinessException.fail("找到指定的打卡任务"));
|
|
|
+
|
|
|
+ SimpleDateFormat sdf = DateUtils.buildDateFormat();
|
|
|
+ YearMonth yearMonth = YearMonth.of(query.getYear(), query.getMonth());
|
|
|
+ // 本月第一日
|
|
|
+ LocalDate firstOfMonth = yearMonth.atDay(1);
|
|
|
+ // 本月最后以日
|
|
|
+ LocalDate endOfMonth = yearMonth.atEndOfMonth();
|
|
|
+ // 任务创建日期
|
|
|
+ LocalDate punchInCreationDate = punchIn.getCreationTime().toLocalDateTime().toLocalDate();
|
|
|
+
|
|
|
+ // 获取打卡记录
|
|
|
+ PunchInRecordQuery punchInRecordQuery = new PunchInRecordQuery();
|
|
|
+ punchInRecordQuery.setPunchInId(punchIn.getId());
|
|
|
+ punchInRecordQuery.setStartDate(String.format("%s 00:00:00.000", firstOfMonth));
|
|
|
+ punchInRecordQuery.setEndDate(String.format("%s 23:59:59.999", endOfMonth));
|
|
|
+ List<PunchInRecord> punchInRecords = punchInRecordService.listByCondition(punchInRecordQuery);
|
|
|
+
|
|
|
+ // 构造数据,日历部分的数据只需要已打卡的数据
|
|
|
+ List<PunchInCalendarDataVO> punchInCalendarDataVOS = new ArrayList<>();
|
|
|
+ List<PunchInRecordDataVO> punchInRecordDtoList = new ArrayList<>();
|
|
|
+ for (PunchInRecord punchInRecord : punchInRecords) {
|
|
|
+ PunchInRecordDataVO punchInRecordDataVO = new PunchInRecordDataVO();
|
|
|
+ BeanUtils.copyProperties(punchInRecord, punchInRecordDataVO);
|
|
|
+ punchInRecordDtoList.add(punchInRecordDataVO);
|
|
|
+
|
|
|
+ if (PunchInStatusV1Enum.UN_FINISH.equals(punchInRecord.getPunchInStatus())
|
|
|
+ || PunchInStatusV1Enum.DOING.equals(punchInRecord.getPunchInStatus())) {
|
|
|
+ continue;
|
|
|
}
|
|
|
+ PunchInCalendarDataVO punchInCalendarDataVO = new PunchInCalendarDataVO();
|
|
|
+ punchInCalendarDataVO.setPunchInDate(punchInRecord.getPunchInDate());
|
|
|
+ punchInCalendarDataVO.setInfo("打卡");
|
|
|
+ punchInCalendarDataVO.setDate(punchInRecord.getPunchInDate());
|
|
|
+ punchInCalendarDataVOS.add(punchInCalendarDataVO);
|
|
|
+ }
|
|
|
|
|
|
- return ContinueStageEnum.NORMAL_STAGE;
|
|
|
+ // 计算全勤率
|
|
|
+ BigDecimal punchInRate = BigDecimal.ZERO;
|
|
|
+ // 要考虑任务刚创建的情况,任务较迟创建的话则使用任务创建时间
|
|
|
+ long dayLength = ChronoUnit.DAYS
|
|
|
+ .between(firstOfMonth.isBefore(punchInCreationDate) ? punchInCreationDate : firstOfMonth, LocalDate.now());
|
|
|
+ if (dayLength != 0) {
|
|
|
+ punchInRate = BigDecimal.valueOf(punchInCalendarDataVOS.size())
|
|
|
+ .divide(BigDecimal.valueOf(dayLength), 4, RoundingMode.HALF_DOWN).multiply(ONE_HUNDRED);
|
|
|
}
|
|
|
|
|
|
- return ContinueStageEnum.NONE;
|
|
|
+ // 构造返回结果
|
|
|
+ PunchInDataVO punchInDataVO = new PunchInDataVO();
|
|
|
+ punchInDataVO.setStartDate(sdf.format(punchIn.getCreationTime()));
|
|
|
+ punchInDataVO.setEndDate(LocalDate.now().toString());
|
|
|
+ punchInDataVO.setPunchInNum(punchInCalendarDataVOS.size());
|
|
|
+ punchInDataVO.setCalendarSelected(punchInCalendarDataVOS);
|
|
|
+ punchInDataVO.setPunchInRecords(punchInRecordDtoList);
|
|
|
+ punchInDataVO.setPunchInRate(punchInRate);
|
|
|
+
|
|
|
+ return punchInDataVO;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 复制打卡任务信息并把旧的信息归档(审计信息不复制、任务版本号自动加1,任务状态:活跃)
|
|
|
+ * @param id 打卡任务id
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ private PiTask copyAndArchivePiTask(Long id) {
|
|
|
+ // 获取旧的打卡任务信息
|
|
|
+ PiTask oldPiTask = Optional.ofNullable(piTaskService.getById(id)).orElseThrow(() -> BusinessException.fail("打卡任务不存在"));
|
|
|
+
|
|
|
+ // 旧的打卡任务信息归档
|
|
|
+ PiTask updatePiTask = new PiTask();
|
|
|
+ updatePiTask.setId(oldPiTask.getId());
|
|
|
+ updatePiTask.setTaskStatus(PunchInTaskStatusEnum.ARCHIVE);
|
|
|
+ piTaskService.update(updatePiTask);
|
|
|
+
|
|
|
+ // 新的打卡任务信息
|
|
|
+ PiTask piTask = new PiTask();
|
|
|
+ BeanUtils.copyProperties(oldPiTask, piTask);
|
|
|
+ piTask.setId(null);
|
|
|
+ piTask.setCreatedBy(null);
|
|
|
+ piTask.setCreationTime(null);
|
|
|
+ piTask.setLastUpdatedBy(null);
|
|
|
+ piTask.setLastUpdateTime(null);
|
|
|
+ piTask.setVersion(1);
|
|
|
+ piTask.setDeleteFlag(false);
|
|
|
+ piTask.setTaskStatus(PunchInTaskStatusEnum.ACTIVE);
|
|
|
+ piTask.setTaskVersion(Optional.ofNullable(oldPiTask.getTaskVersion()).orElse(0) + 1);
|
|
|
+ return piTask;
|
|
|
}
|
|
|
}
|