package com.punchsettle.server.service.manager.impl; import java.sql.Timestamp; 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.function.Function; import java.util.stream.Collectors; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.CollectionUtils; import com.punchsettle.server.atomic.entity.PunchIn; import com.punchsettle.server.atomic.entity.PunchInRecord; import com.punchsettle.server.atomic.entity.PunchInRecordSettlementRela; import com.punchsettle.server.atomic.entity.PunchInSettlement; import com.punchsettle.server.atomic.entity.SettlementTask; import com.punchsettle.server.atomic.entity.User; import com.punchsettle.server.atomic.service.IPunchInRecordService; import com.punchsettle.server.atomic.service.IPunchInRecordSettlementRelaService; import com.punchsettle.server.atomic.service.IPunchInService; import com.punchsettle.server.atomic.service.IPunchInSettlementService; import com.punchsettle.server.atomic.service.ISettlementTaskService; import com.punchsettle.server.atomic.service.IUserService; import com.punchsettle.server.dto.punchin.PunchInQuery; import com.punchsettle.server.dto.punchin.PunchInRecordQuery; import com.punchsettle.server.dto.task.SettleRewardTaskDto; import com.punchsettle.server.service.manager.ISettleManager; import com.punchsettle.server.utiis.DateUtils; import lombok.extern.slf4j.Slf4j; /** * @author tyuio * @version 1.0.0 * @description 结算服务类 * @date 2024/12/12 22:29 */ @Slf4j @Service public class SettleManagerImpl implements ISettleManager { @Autowired private IPunchInService punchInService; @Autowired private IPunchInRecordService punchInRecordService; @Autowired private IUserService userService; @Autowired private IPunchInSettlementService punchInSettlementService; @Autowired private ISettlementTaskService settlementTaskService; @Autowired private IPunchInRecordSettlementRelaService punchInRecordSettlementRelaService; @Override public void settleReward() { } @Override @Transactional(rollbackFor = Exception.class) public void settleReward(SettleRewardTaskDto taskDto) { if (Objects.isNull(taskDto) || Objects.isNull(taskDto.getSettleDate())) { log.info("结算任务异常,原因:没有指定结算日期"); return; } log.info("结算任务开始,结算日期:{}, 结算用户:{}", taskDto.getSettleDate(), taskDto.getUserId()); Timestamp settleStartTime = new Timestamp(System.currentTimeMillis()); // 获取昨天的日期, LocalDate settleDate = LocalDate.parse(taskDto.getSettleDate()); String settleDateStr = taskDto.getSettleDate(); // 判断是否是周末 boolean weekendFlag = DayOfWeek.SATURDAY.equals(settleDate.getDayOfWeek()) || DayOfWeek.SUNDAY.equals(settleDate.getDayOfWeek()); boolean sundayFlag = DayOfWeek.SUNDAY.equals(settleDate.getDayOfWeek()); PunchInRecordQuery recordQuery = new PunchInRecordQuery(); recordQuery.setStartDate(settleDateStr); recordQuery.setEndDate(settleDateStr); List punchInRecords = punchInRecordService.listByCondition(recordQuery); if (CollectionUtils.isEmpty(punchInRecords)) { log.info("结算任务结束,原因:没有打卡记录"); return; } List userIds = punchInRecords.stream().map(PunchInRecord::getCreatedBy).collect(Collectors.toList()); // 读取用户的打卡任务 PunchInQuery punchInQuery = new PunchInQuery(); punchInQuery.setUserIds(userIds); List punchIns = punchInService.listByCondition(punchInQuery); if (CollectionUtils.isEmpty(punchIns)) { log.info("结算任务结束,原因:根据打卡记录没有找到打卡任务"); return; } // 读取用户奖励数据 List users = userService.listByIds(userIds); if (CollectionUtils.isEmpty(users)) { log.info("结算任务结束,原因:没有找到用户奖励信息"); return; } // 获取一周的打卡记录 Map> punchInRecordForWeek = Map.of(); if (sundayFlag) { List punchInIds = punchIns.stream().map(PunchIn::getId).collect(Collectors.toList()); PunchInRecordQuery recordForWeekQuery = new PunchInRecordQuery(); recordForWeekQuery.setPunchInIds(punchInIds); recordForWeekQuery.setStartDate(DateUtils.getLastWeekMondayStr()); recordForWeekQuery.setEndDate(DateUtils.getLastWeekSundayStr()); List punchInRecordForWeeks = punchInRecordService.listByCondition(recordForWeekQuery); if (!CollectionUtils.isEmpty(punchInRecordForWeeks)) { punchInRecordForWeek = punchInRecordForWeeks.stream().collect(Collectors.groupingBy(PunchInRecord::getPunchInId)); } } // 打卡任务容器 Map punchInMap = punchIns.stream().collect(Collectors.toMap(PunchIn::getId, Function.identity(), (key1, key2) -> key1)); // 用户-打卡记录分组 Map> userPunchInRecordMap = punchInRecords.stream().collect(Collectors.groupingBy(PunchInRecord::getCreatedBy)); // 用户-奖励分组 Map userRewardMap = users.stream() .collect(Collectors.toMap(User::getId, Function.identity(), (key1, key2) -> key1)); // 先创建结算任务执行记录 SettlementTask settlementTask = new SettlementTask(); settlementTask.setSettleDate(settleDateStr); settlementTask.setStartTime(settleStartTime); settlementTask.setProcessedNum(userPunchInRecordMap.size()); settlementTaskService.insert(settlementTask); // 结算时间 Timestamp settlementTime = new Timestamp(System.currentTimeMillis()); List addPunchInSettlements = new ArrayList<>(); List updateUsers = new ArrayList<>(); List punchInRecordSettlementRelas = new ArrayList<>(); // 有打卡记录的打卡任务则进行结算 for (Long userId : userPunchInRecordMap.keySet()) { // 获取用户打卡记录 List punchInRecordList = userPunchInRecordMap.get(userId); if (CollectionUtils.isEmpty(punchInRecordList)) { log.info("用户{}没有打卡记录,无须结算", userId); continue; } // 获取用户打卡奖励 User user = userRewardMap.get(userId); if (Objects.isNull(user)) { log.info("用户{}没有奖励信息,无法结算", userId); continue; } // 根据打卡记录上的打卡任务ID获取具体的打卡任务信息进行结算 int settleRewardNum = 0; for (PunchInRecord punchInRecord : punchInRecordList) { PunchIn punchIn = punchInMap.get(punchInRecord.getPunchInId()); if (Objects.isNull(punchIn)) { continue; } // 周末双倍奖励,否则计算普通奖励 settleRewardNum += weekendFlag ? punchIn.getRewardNum() * 2 : punchIn.getRewardNum(); // 周日计算一次全勤双倍奖励 if (sundayFlag && punchIn.getFullAttendanceFlag()) { List tempRecordList = punchInRecordForWeek.get(punchInRecord.getPunchInId()); if (!CollectionUtils.isEmpty(tempRecordList) && tempRecordList.size() >= 6) { settleRewardNum += punchIn.getRewardNum() * 2; } } // 构建结算任务与记录关联信息 PunchInRecordSettlementRela rela = new PunchInRecordSettlementRela(); rela.setRecordId(punchInRecord.getId()); rela.setSettlementId(settlementTask.getId()); punchInRecordSettlementRelas.add(rela); } // 计算结算前后,用户奖励数的变化 int beforeSettleRewardNum = user.getUnclaimedRewardNum(); int afterSettleRewardNum = beforeSettleRewardNum + settleRewardNum; int totalRewardNum = user.getTotalRewardNum() + settleRewardNum; // 构造结算信息 PunchInSettlement addPunchInSettlement = new PunchInSettlement(); addPunchInSettlement.setSettlementTaskId(settlementTask.getId()); addPunchInSettlement.setUserId(userId); addPunchInSettlement.setSettleRewardNum(settleRewardNum); addPunchInSettlement.setSettlementTime(settlementTime); addPunchInSettlement.setBeforeSettleRewardNum(beforeSettleRewardNum); addPunchInSettlement.setAfterSettleRewardNum(afterSettleRewardNum); addPunchInSettlements.add(addPunchInSettlement); // 构造用户奖励信息 User updateUser = new User(); updateUser.setId(user.getId()); updateUser.setTotalRewardNum(totalRewardNum); updateUser.setUnclaimedRewardNum(afterSettleRewardNum); updateUsers.add(updateUser); } // 更新用户奖励信息 userService.batchUpdateUser(updateUsers); // 新增结算信息 punchInSettlementService.batchInsert(addPunchInSettlements); // 构造并新增关联信息 punchInRecordSettlementRelaService.batchInsert(punchInRecordSettlementRelas); // 构造并新增结算任务信息 settlementTask.setProcessedSettleNum(addPunchInSettlements.size()); settlementTask .setProcessedUnsettleNum(settlementTask.getProcessedNum() - settlementTask.getProcessedSettleNum()); settlementTask.setEndTime(new Timestamp(System.currentTimeMillis())); settlementTaskService.update(settlementTask); log.info("结算任务结束"); } }