package com.punchsettle.server.service.manager.impl; import java.math.BigDecimal; import java.math.RoundingMode; import java.time.DayOfWeek; import java.time.LocalDate; import java.util.ArrayList; 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.Account; import com.punchsettle.server.atomic.entity.AccountTransferHistory; import com.punchsettle.server.atomic.service.IAccountService; import com.punchsettle.server.atomic.service.IAccountTransferHistoryService; import com.punchsettle.server.constant.AccountCategoryEnum; import com.punchsettle.server.constant.VersionStatusEnum; import com.punchsettle.server.constant.TransferCategoryEnum; import com.punchsettle.server.pojo.punchIn.AccountQuery; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import com.punchsettle.server.atomic.entity.PiMultiTask; import com.punchsettle.server.atomic.entity.PiMultiTaskExt; import com.punchsettle.server.atomic.entity.PiMultiTaskHistory; import com.punchsettle.server.atomic.entity.PiMultiTaskRela; import com.punchsettle.server.atomic.entity.PiStatus; import com.punchsettle.server.atomic.entity.PiStatusHistory; import com.punchsettle.server.atomic.entity.PiTask; import com.punchsettle.server.atomic.entity.PiTaskExt; import com.punchsettle.server.atomic.entity.PiTaskHistory; import com.punchsettle.server.atomic.entity.SettlePointsHistory; import com.punchsettle.server.atomic.entity.StatPiTaskMonth; import com.punchsettle.server.atomic.entity.StatPiTaskWeek; import com.punchsettle.server.atomic.entity.User; import com.punchsettle.server.atomic.service.IPiMultiTaskExtService; import com.punchsettle.server.atomic.service.IPiMultiTaskHistoryService; import com.punchsettle.server.atomic.service.IPiMultiTaskRelaService; import com.punchsettle.server.atomic.service.IPiMultiTaskService; import com.punchsettle.server.atomic.service.IPiStatusHistoryService; import com.punchsettle.server.atomic.service.IPiStatusService; import com.punchsettle.server.atomic.service.IPiTaskExtService; import com.punchsettle.server.atomic.service.IPiTaskHistoryService; import com.punchsettle.server.atomic.service.IPiTaskService; import com.punchsettle.server.atomic.service.ISettlePointsHistoryService; import com.punchsettle.server.atomic.service.IStatPiTaskMonthService; import com.punchsettle.server.atomic.service.IStatPiTaskWeekService; import com.punchsettle.server.atomic.service.IUserService; import com.punchsettle.server.constant.ArchiveStatusEnum; import com.punchsettle.server.constant.ContinueStageEnum; import com.punchsettle.server.constant.ContinueStatusEnum; import com.punchsettle.server.constant.PunchInResultEnum; import com.punchsettle.server.constant.SettleResultEnum; import com.punchsettle.server.pojo.punchIn.PiMultiTaskExtQuery; import com.punchsettle.server.pojo.punchIn.PiMultiTaskHistoryQuery; import com.punchsettle.server.pojo.punchIn.PiMultiTaskQuery; import com.punchsettle.server.pojo.punchIn.PiStatusQuery; import com.punchsettle.server.pojo.punchIn.PiTaskData; import com.punchsettle.server.pojo.punchIn.PiTaskExtQuery; import com.punchsettle.server.pojo.punchIn.PiTaskHistoryQuery; import com.punchsettle.server.pojo.punchIn.PiTaskQuery; import com.punchsettle.server.pojo.punchIn.PunchInSettleData; import com.punchsettle.server.service.manager.ICalendarManager; import com.punchsettle.server.service.manager.IPunchInCoreManager; import com.punchsettle.server.service.manager.IPunchInSettleManager; import com.punchsettle.server.service.manager.ISettleManager; import com.punchsettle.server.utiis.DateUtils; import lombok.extern.slf4j.Slf4j; /** * @author tyuio * @version 1.0.0 * @date 2025/4/18 16:39 * @description 打卡结算服务类 */ @Slf4j @Component public class PunchInSettleManagerImpl implements IPunchInSettleManager { /** * 默认数值100 */ private static final BigDecimal ONE_HUNDRED = new BigDecimal(100); /** * 默认百分比 0.00% */ private static final BigDecimal ZERO_RATE = new BigDecimal("0.00"); @Autowired private IPiTaskService piTaskService; @Autowired private IPiTaskExtService piTaskExtService; @Autowired private IPiTaskHistoryService piTaskHistoryService; @Autowired private IStatPiTaskMonthService statPiTaskMonthService; @Autowired private IStatPiTaskWeekService statPiTaskWeekService; @Autowired private IPiStatusService piStatusService; @Autowired private IPiStatusHistoryService piStatusHistoryService; @Autowired private IPiMultiTaskService piMultiTaskService; @Autowired private IPiMultiTaskExtService piMultiTaskExtService; @Autowired private IPiMultiTaskHistoryService piMultiTaskHistoryService; @Autowired private IPiMultiTaskRelaService piMultiTaskRelaService; @Autowired private ICalendarManager calendarManager; @Autowired private IUserService userService; @Autowired private ISettlePointsHistoryService settlePointsHistoryService; @Autowired private IPunchInCoreManager punchInManager; @Autowired private ISettleManager settleManager; @Autowired private IAccountService accountService; @Autowired private IAccountTransferHistoryService accountTransferHistoryService; @Override @Transactional(rollbackFor = Exception.class) public void punchInSettle(List userIds, String punchInDateStr, Long settleTaskHistoryId) { // 打卡日期 LocalDate punchInDate = LocalDate.parse(punchInDateStr); // 是否周一 boolean isMonday = DayOfWeek.MONDAY.equals(punchInDate.getDayOfWeek()); // 是否周日 boolean isSunday = DayOfWeek.SUNDAY.equals(punchInDate.getDayOfWeek()); // 是否打卡所在月第一天 boolean isFirstDayOfMonth = punchInDate.getDayOfMonth() == 1; // 是否打卡所在月最后一天 boolean isLastDayOfMonth = punchInDate.getDayOfMonth() == punchInDate.lengthOfMonth(); // 周期数 String yearWeek = DateUtils.getYearWeek(punchInDate); // 月份数 String yearMonth = DateUtils.getYearMonth(punchInDate); // 打卡任务状态记录 新增列表 List addPiStatusHistories = new ArrayList<>(); // 打卡任务周统计 新增列表 List addStatPiTaskWeekList = new ArrayList<>(); // 打卡任务月统计 新增列表 List addStatPiTaskMonthList = new ArrayList<>(); // 结算积分记录 新增列表 List addSettlePointsHistories = new ArrayList<>(); // 转张记录 新增列表 List addAccountTransferHistories = new ArrayList<>(); // 账户 更新列表 List updateAccountList = new ArrayList<>(); // 用户信息 更新列表 List updateUserList = new ArrayList<>(); // 打卡状态 更新列表 List updatePiStatusList = new ArrayList<>(); // 打卡任务记录 更新列表 List updatePunchInTaskHistories = new ArrayList<>(); // 打卡多任务记录 更新列表 List updatePunchInMultiTaskHistories = new ArrayList<>(); // 获取结算数据 List punchInSettleData = getPunchInSettleData(userIds, punchInDateStr); // 打卡结算逻辑 for (PunchInSettleData punchInSettle : punchInSettleData) { // 结算总积分 int settlePoints = 0; // 单任务处理部分 for (PiTaskData piTaskData : punchInSettle.getPiTaskDataList()) { // 打卡任务 PiTask piTask = piTaskData.getPiTask(); // 打卡任务打卡记录 PiTaskHistory piTaskHistory = piTaskData.getPiTaskHistory(); // 打卡任务状态 PiStatus piStatus = piTaskData.getPiStatus(); // 打卡任务拖扎信息 List piTaskExtList = piTaskData.getPiTaskExtList(); // 状态变更前记录历史状态 PiStatusHistory piStatusHistoryInTask = new PiStatusHistory(); BeanUtils.copyProperties(piStatus, piStatusHistoryInTask); addPiStatusHistories.add(piStatusHistoryInTask); // 打卡记录 PiTaskHistory updatePiTaskHistory = new PiTaskHistory(); updatePiTaskHistory.setId(piTaskHistory.getId()); // 记录当前状态数据 updatePiTaskHistory.setTaskContinueStatus(piStatus.getTaskContinueStatus()); updatePiTaskHistory.setTaskContinueDay(piStatus.getTaskContinueDay()); updatePiTaskHistory.setContinueStage(piStatus.getContinueStage()); updatePiTaskHistory.setStageStartDate(piStatus.getStageStartDate()); updatePiTaskHistory.setStageEndDate(piStatus.getStageEndDate()); updatePiTaskHistory.setContinueInterruptedCount(piStatus.getContinueInterruptedCount()); // 判断打卡结果 PunchInResultEnum punchInResult = punchInManager.judgePunchInResultInTask(piTask, piTaskHistory); punchInSettle.getPiMultiTaskHistory().setPunchInResult(punchInResult); updatePiTaskHistory.setPunchInResult(punchInResult); // 更新打卡状态 piStatus.setStatusDate(punchInDateStr); refreshPiStatus(piStatus, punchInResult, piTask, piTaskHistory, punchInDate, isMonday, isFirstDayOfMonth, yearWeek, yearMonth); // 计算积分,要先刷新打卡状态 int taskPoints = settleManager.calculatePointsInTask(piTask, piTaskExtList, piTaskHistory, piStatus); settlePoints += taskPoints; // 更新打卡状态 piStatus.setPointsInWeek(piStatus.getPointsInWeek() + taskPoints); piStatus.setPointsInMonth(piStatus.getPointsInMonth() + taskPoints); // 打卡记录 更新 updatePiTaskHistory.setSettlePoints(taskPoints); updatePiTaskHistory.setSettleResult(SettleResultEnum.SETTLED); updatePiTaskHistory.setSettlePiTaskId(piTask.getId()); updatePiTaskHistory.setSettleTaskHistoryId(settleTaskHistoryId); updatePiStatusList.add(piStatus); updatePunchInTaskHistories.add(updatePiTaskHistory); // 周日构建周统计数据 if (isSunday) { StatPiTaskWeek statPiTaskWeek = buildStatPiTaskWeek(punchInSettle.getUserId(), piTask, piStatus); addStatPiTaskWeekList.add(statPiTaskWeek); } // 月末构建月统计数据 if (isLastDayOfMonth) { StatPiTaskMonth statPiTaskMonth = buildStatPiTaskMonth(punchInSettle.getUserId(), piTask, piStatus); addStatPiTaskMonthList.add(statPiTaskMonth); } } // 打卡多任务 PiMultiTask piMultiTask = punchInSettle.getPiMultiTask(); // 打卡多任务打卡记录 PiMultiTaskHistory piMultiTaskHistory = punchInSettle.getPiMultiTaskHistory(); // 打卡多任务状态 PiStatus piStatusInMultiTask = punchInSettle.getPiStatus(); // 状态变更前记录历史状态 PiStatusHistory piStatusHistoryInMultiTask = new PiStatusHistory(); BeanUtils.copyProperties(piStatusInMultiTask, piStatusHistoryInMultiTask); addPiStatusHistories.add(piStatusHistoryInMultiTask); // 多任务处理部分 PiMultiTaskHistory updatePiMultiTaskHistory = new PiMultiTaskHistory(); // 判断多任务打卡状态并设置 PunchInResultEnum punchInResult = punchInManager.judgePunchInResultInMultiTask(piMultiTask, punchInSettle.getRelaPunchInTaskHistories()); piMultiTaskHistory.setPunchInResult(punchInResult); updatePiMultiTaskHistory.setPunchInResult(punchInResult); // 这里少了连续阶段的判断 // 设置多任务统计时间 piStatusInMultiTask.setStatusDate(punchInDateStr); // 刷新打卡状态中的连续任务数据 refreshContinueData(piStatusInMultiTask, punchInResult, piMultiTask, punchInDate); // 计算多任务积分 int multiTaskPoints = settleManager.calculatePointsInMultiTask(piMultiTask, punchInSettle.getPiMultiTaskExtList(), piMultiTaskHistory, piStatusInMultiTask); settlePoints += multiTaskPoints; // 设置打卡记录表信息 updatePiMultiTaskHistory.setSettlePoints(multiTaskPoints); updatePiMultiTaskHistory.setSettleResult(SettleResultEnum.SETTLED); updatePiMultiTaskHistory.setSettleTaskHistoryId(settleTaskHistoryId); updatePunchInMultiTaskHistories.add(updatePiMultiTaskHistory); // 获取并设置用户信息 User user = punchInSettle.getUser(); Integer beforeTotalPoints = Optional.ofNullable(user.getTotalPoints()).orElse(0); Integer beforeUnusedPoints = Optional.ofNullable(user.getUnusedPoints()).orElse(0); User updateUser = new User(); updateUser.setId(user.getId()); updateUser.setTotalPoints(beforeTotalPoints + settlePoints); updateUser.setUnusedPoints(beforeUnusedPoints + settlePoints); updateUserList.add(user); // 更新账户信息 Account account = punchInSettle.getAccount(); Integer beforeAccountPoints = Optional.ofNullable(account.getPoints()).orElse(0); account.setPoints(beforeAccountPoints + settlePoints); updateAccountList.add(account); // 增加账户转账记录 AccountTransferHistory accountTransferHistory = new AccountTransferHistory(); accountTransferHistory.setTransferPoints(settlePoints); accountTransferHistory.setTransferCategory(TransferCategoryEnum.SETTLE); accountTransferHistory.setRecipientAccountId(account.getId()); accountTransferHistory.setRaPointsAfterTransfer(beforeAccountPoints); accountTransferHistory.setRaPointsAfterTransfer(account.getPoints()); addAccountTransferHistories.add(accountTransferHistory); // 设置结算积分记录 SettlePointsHistory addSettlePointsHistory = new SettlePointsHistory(); addSettlePointsHistory.setSettleTaskHistoryId(settleTaskHistoryId); addSettlePointsHistory.setUserId(user.getId()); addSettlePointsHistory.setSettleDate(punchInDateStr); addSettlePointsHistory.setSettlePoints(settlePoints); addSettlePointsHistory.setBeforeSettlePoints(beforeTotalPoints); addSettlePointsHistory.setAfterSettlePoints(beforeTotalPoints + settlePoints); addSettlePointsHistories.add(addSettlePointsHistory); } // 数据入库 if (!CollectionUtils.isEmpty(updateUserList)) { userService.batchUpdateUser(updateUserList); } if (!CollectionUtils.isEmpty(addSettlePointsHistories)) { settlePointsHistoryService.insertList(addSettlePointsHistories); } if (!CollectionUtils.isEmpty(addPiStatusHistories)) { piStatusHistoryService.insertList(addPiStatusHistories); } if (!CollectionUtils.isEmpty(addStatPiTaskWeekList)) { statPiTaskWeekService.insertList(addStatPiTaskWeekList); } if (!CollectionUtils.isEmpty(addStatPiTaskMonthList)) { statPiTaskMonthService.insertList(addStatPiTaskMonthList); } if (!CollectionUtils.isEmpty(updatePiStatusList)) { piStatusService.batchUpdate(updatePiStatusList); } if (!CollectionUtils.isEmpty(updatePunchInTaskHistories)) { piTaskHistoryService.batchUpdate(updatePunchInTaskHistories); } if (!CollectionUtils.isEmpty(updatePunchInMultiTaskHistories)) { piMultiTaskHistoryService.batchUpdate(updatePunchInMultiTaskHistories); } if (!CollectionUtils.isEmpty(updateAccountList)) { accountService.batchUpdate(updateAccountList); } if (!CollectionUtils.isEmpty(addAccountTransferHistories)) { accountTransferHistoryService.batchInsert(addAccountTransferHistories); } } /** * 获取用户ID-打卡结算数据关联 * * @param userIds 设计的用户 * @param punchInDateStr 打卡日期 * @return */ private List getPunchInSettleData(List userIds, String punchInDateStr) { // 用户信息, 用户ID-用户信息关联 List users = userService.listByIds(userIds); Map userMap = users.stream().collect(Collectors.toMap(User::getId, Function.identity(), (key1, key2) -> key1)); // 获取账户信息,用户ID-账户信息关联 AccountQuery accountQuery = new AccountQuery(); accountQuery.setAccountCategory(AccountCategoryEnum.BASIC); accountQuery.setUserIds(userIds); List accounts = accountService.getAccountByCondition(accountQuery); Map accountMap = accounts.stream().collect(Collectors.toMap(Account::getUserId, Function.identity(), (key1, key2) -> key1)); // 获取多任务信息,用户ID-多任务关联 PiMultiTaskQuery piMultiTaskQuery = new PiMultiTaskQuery(); piMultiTaskQuery.setMultiTaskTaskStatus(VersionStatusEnum.ACTIVE); piMultiTaskQuery.setUserIds(userIds); List piMultiTasks = piMultiTaskService.queryByCondition(piMultiTaskQuery); Map piMultiTaskMap = piMultiTasks.stream() .collect(Collectors.toMap(PiMultiTask::getUserId, Function.identity(), (key1, key2) -> key1)); // 多任务ID Set multiTaskIds = piMultiTasks.stream().map(PiMultiTask::getId).collect(Collectors.toSet()); // 多任务唯一ID Set multiTaskUniqueIds = piMultiTasks.stream().map(PiMultiTask::getUniqueId).collect(Collectors.toSet()); // 获取多任务拓展信息,多任务ID-多任务拓展关联 PiMultiTaskExtQuery piMultiTaskExtQuery = new PiMultiTaskExtQuery(); piMultiTaskExtQuery.setMultiTaskIds(multiTaskIds); List piMultiTaskExtList = piMultiTaskExtService.queryByCondition(piMultiTaskExtQuery); Map> piMultiTaskExtMap = piMultiTaskExtList.stream().collect(Collectors.groupingBy(PiMultiTaskExt::getMultiTaskId)); // 获取多任务打卡历史信息,多任务唯一ID-多任务打卡历史关联 PiMultiTaskHistoryQuery piMultiTaskHistoryQuery = new PiMultiTaskHistoryQuery(); piMultiTaskHistoryQuery.setPunchInMultiTaskUniqueIds(multiTaskUniqueIds); piMultiTaskHistoryQuery.setPunchInDate(punchInDateStr); List piMultiTaskHistories = piMultiTaskHistoryService.queryByCondition(piMultiTaskHistoryQuery); Map piMultiTaskHistoryMap = piMultiTaskHistories.stream().collect( Collectors.toMap(PiMultiTaskHistory::getMultiTaskUniqueId, Function.identity(), (key1, key2) -> key1)); // 打卡任务状态 PiStatusQuery piStatusQuery = new PiStatusQuery(); piStatusQuery.setUserIds(userIds); List piStatusList = piStatusService.queryByCondition(piStatusQuery); // 打卡任务状态,多任务唯一ID-打卡状态关联 Map piStatusMapInMultiTask = piStatusList.stream().filter(v -> Objects.nonNull(v.getMultiTaskUniqueId())).collect(Collectors.toMap(PiStatus::getMultiTaskUniqueId, Function.identity(), (key1, key2) -> key1)); // 打卡任务状态,任务唯一ID-打卡状态关联 Map piStatusMapInTask = piStatusList.stream().filter(v -> Objects.nonNull(v.getTaskUniqueId())).collect(Collectors.toMap(PiStatus::getTaskUniqueId, Function.identity(), (key1, key2) -> key1)); // 多任务关联打卡任务,多任务ID-多任务关联打卡任务关联 List piMultiTaskRelaList = piMultiTaskRelaService.queryByMultiTaskId(multiTaskIds); Map> piMultiTaskRelaMap = piMultiTaskRelaList.stream().collect(Collectors.groupingBy(PiMultiTaskRela::getMultiTaskId)); // 获取打卡任务信息,打卡任务唯一ID-打卡任务关联 PiTaskQuery piTaskQuery = new PiTaskQuery(); piTaskQuery.setTaskStatus(VersionStatusEnum.ACTIVE); piTaskQuery.setArchiveStatus(ArchiveStatusEnum.ACTIVE); piTaskQuery.setUserIds(userIds); List piTasks = piTaskService.queryByCondition(piTaskQuery); Map> piTaskMap = piTasks.stream().collect(Collectors.groupingBy(PiTask::getCreatedBy)); // 获取打卡记录,任务唯一 ID-打卡记录关联 PiTaskHistoryQuery piTaskHistoryQuery = new PiTaskHistoryQuery(); piTaskHistoryQuery.setPunchInDate(punchInDateStr); piTaskHistoryQuery.setUserIds(userIds); List punchInTaskHistories = piTaskHistoryService.queryByCondition(piTaskHistoryQuery); Map piTaskHistoryMap = punchInTaskHistories.stream().collect(Collectors.toMap(PiTaskHistory::getTaskUniqueId, Function.identity(), (key1, key2) -> key1)); // 打卡任务ID Set punchInTaskIds = piTasks.stream().map(PiTask::getId).collect(Collectors.toSet()); // 获取打卡任务拓展表,打卡任务ID-打卡任务拓展关联 PiTaskExtQuery piTaskExtQuery = new PiTaskExtQuery(); piTaskExtQuery.setPunchInTaskIds(punchInTaskIds); List piTaskExtList = piTaskExtService.queryByCondition(piTaskExtQuery); Map> piTaskExtGroupList = piTaskExtList.stream().collect(Collectors.groupingBy(PiTaskExt::getTaskId)); return userIds.stream().map(userId -> { PunchInSettleData punchInSettleData = new PunchInSettleData(); // 设置用户ID punchInSettleData.setUserId(userId); // 获取并设置用户信息 User user = userMap.get(userId); punchInSettleData.setUser(user); // 获取并设置账户信息 Account account = accountMap.get(userId); punchInSettleData.setAccount(account); // TODO 获取并设置多任务打卡信息,这个不可能为空,为空则用户初始注册时创建时有问题 PiMultiTask piMultiTask = piMultiTaskMap.get(userId); punchInSettleData.setPiMultiTask(piMultiTask); // 获取并设置对应的拓展信息 List tempPiMultiTaskExtList = piMultiTaskExtMap.get(piMultiTask.getId()); punchInSettleData.setPiMultiTaskExtList(tempPiMultiTaskExtList); // 获取并设置对应的多任务打卡记录 PiMultiTaskHistory piMultiTaskHistory = piMultiTaskHistoryMap.get(piMultiTask.getUniqueId()); punchInSettleData.setPiMultiTaskHistory(piMultiTaskHistory); // 获取多任务与打卡任务的关联信息 List tempPiMultiTaskRelaList = piMultiTaskRelaMap.get(piMultiTask.getId()); Set relaContainTaskIdList = tempPiMultiTaskRelaList.stream().map(PiMultiTaskRela::getTaskId).collect(Collectors.toSet()); // 获取并设置多任务的状态信息 PiStatus piStatusInMultiTask = piStatusMapInMultiTask.get(piMultiTask.getUniqueId()); punchInSettleData.setPiStatus(piStatusInMultiTask); // 获取任务列表 List piTasksList = piTaskMap.get(userId); // 打卡任务数据 List piTaskDataList = new ArrayList<>(piTasksList.size()); // 关联的打卡任务记录 List relaPunchInTaskHistories = new ArrayList<>(relaContainTaskIdList.size()); for (PiTask piTask : piTasksList) { PiTaskData piTaskData = new PiTaskData(); piTaskData.setPiTask(piTask); // 获取并设置打卡任务 PiTaskHistory piTaskHistory = piTaskHistoryMap.get(piTask.getUniqueId()); piTaskData.setPiTaskHistory(piTaskHistory); //设置多任务与打卡记录的关联信息 if (relaContainTaskIdList.contains(piTask.getId())) { relaPunchInTaskHistories.add(piTaskHistory); } // 获取并设置拓展信息 List tempPiTaskExtList = piTaskExtGroupList.get(piTask.getId()); piTaskData.setPiTaskExtList(tempPiTaskExtList); // 获取并设置任务状态 PiStatus piStatusInTask = piStatusMapInTask.get(piTask.getUniqueId()); piTaskData.setPiStatus(piStatusInTask); piTaskDataList.add(piTaskData); } punchInSettleData.setPiTaskDataList(piTaskDataList); punchInSettleData.setRelaPunchInTaskHistories(relaPunchInTaskHistories); return punchInSettleData; }).collect(Collectors.toList()); } /** * 更新打卡任务状态 * @param piStatus 打卡任务状态 * @param punchInResult 打卡结果 * @param piTask 打卡任务 * @param piTaskHistory 打卡任务记录 * @param punchInDate 打卡日期 * @param isMonday 是否周一 * @param isFirstDayOfMonth 是否本月第一天 * @param yearWeek 周数 * @param yearMonth 月份数 */ private void refreshPiStatus(PiStatus piStatus, PunchInResultEnum punchInResult, PiTask piTask, PiTaskHistory piTaskHistory, LocalDate punchInDate, boolean isMonday, boolean isFirstDayOfMonth, String yearWeek, String yearMonth) { // 刷新打卡状态中的连续任务数据 refreshContinueData(piStatus, punchInResult, piTask, punchInDate); // 周一或月初 if (isMonday || isFirstDayOfMonth) { piStatus.setRepeatCategory(piTask.getRepeatCategory()); piStatus.setRepeatCustomDay(piTask.getRepeatCustomDay()); } // 周一 if (isMonday) { piStatus.setStatTimeInWeek(yearWeek); // 设置本周总打卡次数 int PunchInTotalCountInWeek = punchInManager.getPunchInTotalCountInRange(piTask.getRepeatCategory(), piTask.getRepeatCustomDay(), DateUtils.getFirstDayOfWeek(punchInDate), DateUtils.getLastDayOfWeek(punchInDate)); piStatus.setPunchInTotalCountInWeek(PunchInTotalCountInWeek); // 重置数据 piStatus.setPunchInCountInWeek(0); piStatus.setPunchInDoneCountInWeek(0); piStatus.setRepeatPrevTotalCountInWeek(0); piStatus.setRepeatStartDateInWeek(punchInDate); } // 打卡日所在月的第一天 if (isFirstDayOfMonth) { piStatus.setStatTimeInMonth(yearMonth); // 设置本月总打卡次数 int PunchInTotalCountInMonth = punchInManager.getPunchInTotalCountInRange(piTask.getRepeatCategory(), piTask.getRepeatCustomDay(), DateUtils.getFirstDayOfMonth(punchInDate), DateUtils.getLastDayOfMonth(punchInDate)); piStatus.setPunchInTotalCountInMonth(PunchInTotalCountInMonth); // 重置数据 piStatus.setPunchInCountInMonth(0); piStatus.setPunchInDoneCountInMonth(0); piStatus.setRepeatPrevTotalCountInMonth(0); piStatus.setRepeatStartDateInMonth(punchInDate); } // 重复类型发生变换,总打卡次数=历史真实发生的总打卡次数+变换前发生的总打卡次数+变换后可能的总打卡次数 if (!piStatus.getRepeatCategory().equals(piTask.getRepeatCategory())) { // 历史真实发生的总打卡次数(周) Integer oldPrevTotalCountInWeek = Optional.ofNullable(piStatus.getRepeatPrevTotalCountInWeek()).orElse(0); // 变换前发生的总打卡次数(周) int prevTotalCountInWeek = punchInManager.getPunchInTotalCountInRange(piStatus.getRepeatCategory(), piStatus.getRepeatCustomDay(), piStatus.getRepeatStartDateInWeek(), punchInDate.minusDays(1)); // 变换后可能的总打卡次数(周) int punchInTotalCountInWeek = punchInManager.getPunchInTotalCountInRange(piTask.getRepeatCategory(), piTask.getRepeatCustomDay(), punchInDate, DateUtils.getLastDayOfWeek(punchInDate)); // 历史真实发生的总打卡次数(月) Integer oldPrevTotalCountInMonth = Optional.ofNullable(piStatus.getRepeatPrevTotalCountInMonth()).orElse(0); // 变换前发生的总打卡次数(月) int prevTotalCountInMonth = punchInManager.getPunchInTotalCountInRange(piStatus.getRepeatCategory(), piStatus.getRepeatCustomDay(), piStatus.getRepeatStartDateInMonth(), punchInDate.minusDays(1)); // 变换后可能的总打卡次数(月 ) int punchInTotalCountInMonth = punchInManager.getPunchInTotalCountInRange(piTask.getRepeatCategory(), piTask.getRepeatCustomDay(), punchInDate, DateUtils.getLastDayOfMonth(punchInDate)); // 设置实时数据 piStatus.setRepeatPrevTotalCountInWeek(prevTotalCountInWeek + oldPrevTotalCountInWeek); piStatus.setPunchInTotalCountInWeek(piStatus.getRepeatPrevTotalCountInWeek() + punchInTotalCountInWeek); piStatus.setRepeatPrevTotalCountInMonth(prevTotalCountInMonth + oldPrevTotalCountInMonth); piStatus.setPunchInTotalCountInMonth(piStatus.getRepeatPrevTotalCountInMonth() + punchInTotalCountInMonth); } // 存在打卡记录则已打卡数加1 if (Objects.nonNull(piTaskHistory)) { piStatus.setPunchInCountInWeek(piStatus.getPunchInCountInWeek() + 1); piStatus.setPunchInCountInMonth(piStatus.getPunchInCountInMonth() + 1); } // 完成打卡则完成打卡数记录加一 if (PunchInResultEnum.DONE.equals(punchInResult)) { piStatus.setPunchInDoneCountInWeek(piStatus.getPunchInDoneCountInWeek() + 1); piStatus.setPunchInDoneCountInMonth(piStatus.getPunchInDoneCountInMonth() + 1); } } /** * 刷新打卡状态中的连续任务数据 * @param piStatus * @param punchInResult * @param continueTask * @param punchInDate */ private void refreshContinueData(PiStatus piStatus, PunchInResultEnum punchInResult, ContinueTask continueTask, LocalDate punchInDate) { // 设置任务连续状态 ContinueStatusEnum oldTaskContinueStatus = piStatus.getTaskContinueStatus(); piStatus.setTaskContinueStatus(punchInResult.equals(PunchInResultEnum.DONE) ? ContinueStatusEnum.CONTINUE : ContinueStatusEnum.INTERRUPTED); piStatus.setTaskContinueDay(oldTaskContinueStatus.equals(piStatus.getTaskContinueStatus()) ? piStatus.getTaskContinueDay() + 1 : 1); // 旧的连续阶段 ContinueStageEnum oldContinueStage = piStatus.getContinueStage(); // 判断当前处于的连续阶段 ContinueStageEnum continueStageResult = punchInManager.judgeContinueStage(continueTask, punchInResult, piStatus, punchInDate); piStatus.setContinueStage(continueStageResult); // 下面3种情况不处理:宽限期 变 宽限期;正常打卡期 变 正常打卡期;惩罚期 变 惩罚期; // 宽限期 变 正常打卡期,则设置阶段开始时间,重置中断次数 if (ContinueStageEnum.GRACE_STAGE.equals(oldContinueStage) && ContinueStageEnum.NORMAL_STAGE.equals(continueStageResult)) { piStatus.setStageStartDate(punchInDate); piStatus.setContinueInterruptedCount(0); } // 如果正常打卡期 变 惩罚期,则设置阶段开始时间和阶段结束时间,增加中断次数 if (ContinueStageEnum.NORMAL_STAGE.equals(oldContinueStage) && ContinueStageEnum.PENALTY_STAGE.equals(continueStageResult)) { piStatus.setStageStartDate(punchInDate); piStatus.setStageEndDate(punchInDate.plusDays(continueTask.getPenaltyDay())); piStatus.setContinueInterruptedCount(piStatus.getContinueInterruptedCount() + 1); } // 如果惩罚期 变 正常打卡期,则设置阶段开始时间 if (ContinueStageEnum.PENALTY_STAGE.equals(oldContinueStage) && ContinueStageEnum.NORMAL_STAGE.equals(continueStageResult)) { piStatus.setStageStartDate(punchInDate); } } /** * 构建周统计数据 * @param userId 用户ID * @param piTask 打卡任务 * @param piStatus 打卡任务状态 * @return */ private static StatPiTaskWeek buildStatPiTaskWeek(Long userId, PiTask piTask, PiStatus piStatus) { StatPiTaskWeek statPiTaskWeek = new StatPiTaskWeek(); statPiTaskWeek.setUserId(userId); statPiTaskWeek.setTaskUniqueId(piTask.getUniqueId()); statPiTaskWeek.setStatTime(piStatus.getStatTimeInWeek()); statPiTaskWeek.setPunchInTotalCount(piStatus.getPunchInTotalCountInWeek()); statPiTaskWeek.setPunchInCount(piStatus.getPunchInCountInWeek()); statPiTaskWeek.setPunchInDoneCount(piStatus.getPunchInDoneCountInWeek()); statPiTaskWeek.setPoints(piStatus.getPointsInWeek()); Integer punchInTotalCount = Optional.ofNullable(piStatus.getPunchInTotalCountInWeek()).orElse(0); if (punchInTotalCount == 0) { statPiTaskWeek.setPunchInRate(ZERO_RATE); statPiTaskWeek.setPunchInDoneRate(ZERO_RATE); } else { Integer punchInCount = Optional.ofNullable(piStatus.getPunchInCountInWeek()).orElse(0); Integer punchInDoneCount = Optional.ofNullable(piStatus.getPunchInDoneCountInWeek()).orElse(0); BigDecimal totalCount = new BigDecimal(punchInTotalCount); BigDecimal punchInRate = BigDecimal.valueOf(punchInCount).divide(totalCount, 2, RoundingMode.HALF_UP).multiply(ONE_HUNDRED); statPiTaskWeek.setPunchInRate(punchInRate); BigDecimal punchInDoneRate = BigDecimal.valueOf(punchInDoneCount).divide(totalCount, 2, RoundingMode.HALF_UP).multiply(ONE_HUNDRED); statPiTaskWeek.setPunchInDoneRate(punchInDoneRate); } return statPiTaskWeek; } /** * 构建月统计数据 * @param userId 用户ID * @param piTask 打卡任务 * @param piStatus 打卡任务状态 * @return */ private static StatPiTaskMonth buildStatPiTaskMonth(Long userId, PiTask piTask, PiStatus piStatus) { StatPiTaskMonth statPiTaskMonth = new StatPiTaskMonth(); statPiTaskMonth.setUserId(userId); statPiTaskMonth.setTaskUniqueId(piTask.getUniqueId()); statPiTaskMonth.setStatTime(piStatus.getStatTimeInMonth()); statPiTaskMonth.setPunchInTotalCount(piStatus.getPunchInTotalCountInMonth()); statPiTaskMonth.setPunchInCount(piStatus.getPunchInCountInMonth()); statPiTaskMonth.setPunchInDoneCount(piStatus.getPunchInDoneCountInMonth()); statPiTaskMonth.setPoints(piStatus.getPointsInMonth()); Integer punchInTotalCount = Optional.ofNullable(piStatus.getPunchInTotalCountInMonth()).orElse(0); if (punchInTotalCount == 0) { statPiTaskMonth.setPunchInRate(ZERO_RATE); statPiTaskMonth.setPunchInDoneRate(ZERO_RATE); } else { Integer punchInCount = Optional.ofNullable(piStatus.getPunchInCountInMonth()).orElse(0); Integer punchInDoneCount = Optional.ofNullable(piStatus.getPunchInDoneCountInMonth()).orElse(0); BigDecimal totalCount = new BigDecimal(punchInTotalCount); BigDecimal punchInRate = BigDecimal.valueOf(punchInCount).divide(totalCount, 2, RoundingMode.HALF_UP).multiply(ONE_HUNDRED); statPiTaskMonth.setPunchInRate(punchInRate); BigDecimal punchInDoneRate = BigDecimal.valueOf(punchInDoneCount).divide(totalCount, 2, RoundingMode.HALF_UP).multiply(ONE_HUNDRED); statPiTaskMonth.setPunchInDoneRate(punchInDoneRate); } return statPiTaskMonth; } }