|
|
@@ -0,0 +1,238 @@
|
|
|
+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<PunchInRecord> punchInRecords = punchInRecordService.listByCondition(recordQuery);
|
|
|
+ if (CollectionUtils.isEmpty(punchInRecords)) {
|
|
|
+ log.info("结算任务结束,原因:没有打卡记录");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ List<Long> userIds = punchInRecords.stream().map(PunchInRecord::getCreatedBy).collect(Collectors.toList());
|
|
|
+
|
|
|
+ // 读取用户的打卡任务
|
|
|
+ PunchInQuery punchInQuery = new PunchInQuery();
|
|
|
+ punchInQuery.setUserIds(userIds);
|
|
|
+ List<PunchIn> punchIns = punchInService.listByCondition(punchInQuery);
|
|
|
+ if (CollectionUtils.isEmpty(punchIns)) {
|
|
|
+ log.info("结算任务结束,原因:根据打卡记录没有找到打卡任务");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 读取用户奖励数据
|
|
|
+ List<User> users = userService.listByIds(userIds);
|
|
|
+ if (CollectionUtils.isEmpty(users)) {
|
|
|
+ log.info("结算任务结束,原因:没有找到用户奖励信息");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取一周的打卡记录
|
|
|
+ Map<Long, List<PunchInRecord>> punchInRecordForWeek = Map.of();
|
|
|
+ if (sundayFlag) {
|
|
|
+ List<Long> 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<PunchInRecord> punchInRecordForWeeks = punchInRecordService.listByCondition(recordForWeekQuery);
|
|
|
+ if (!CollectionUtils.isEmpty(punchInRecordForWeeks)) {
|
|
|
+ punchInRecordForWeek =
|
|
|
+ punchInRecordForWeeks.stream().collect(Collectors.groupingBy(PunchInRecord::getPunchInId));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 打卡任务容器
|
|
|
+ Map<Long, PunchIn> punchInMap =
|
|
|
+ punchIns.stream().collect(Collectors.toMap(PunchIn::getId, Function.identity(), (key1, key2) -> key1));
|
|
|
+
|
|
|
+ // 用户-打卡记录分组
|
|
|
+ Map<Long, List<PunchInRecord>> userPunchInRecordMap =
|
|
|
+ punchInRecords.stream().collect(Collectors.groupingBy(PunchInRecord::getCreatedBy));
|
|
|
+
|
|
|
+ // 用户-奖励分组
|
|
|
+ Map<Long, User> 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<PunchInSettlement> addPunchInSettlements = new ArrayList<>();
|
|
|
+ List<User> updateUsers = new ArrayList<>();
|
|
|
+ List<PunchInRecordSettlementRela> punchInRecordSettlementRelas = new ArrayList<>();
|
|
|
+
|
|
|
+ // 有打卡记录的打卡任务则进行结算
|
|
|
+ for (Long userId : userPunchInRecordMap.keySet()) {
|
|
|
+ // 获取用户打卡记录
|
|
|
+ List<PunchInRecord> 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<PunchInRecord> 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("结算任务结束");
|
|
|
+ }
|
|
|
+}
|