SettleManagerImpl.java 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. package com.punchsettle.server.service.manager.impl;
  2. import java.sql.Timestamp;
  3. import java.time.DayOfWeek;
  4. import java.time.LocalDate;
  5. import java.util.ArrayList;
  6. import java.util.List;
  7. import java.util.Map;
  8. import java.util.Objects;
  9. import java.util.function.Function;
  10. import java.util.stream.Collectors;
  11. import org.springframework.beans.factory.annotation.Autowired;
  12. import org.springframework.stereotype.Service;
  13. import org.springframework.transaction.annotation.Transactional;
  14. import org.springframework.util.CollectionUtils;
  15. import com.punchsettle.server.atomic.entity.PunchIn;
  16. import com.punchsettle.server.atomic.entity.PunchInRecord;
  17. import com.punchsettle.server.atomic.entity.PunchInRecordSettlementRela;
  18. import com.punchsettle.server.atomic.entity.PunchInSettlement;
  19. import com.punchsettle.server.atomic.entity.SettlementTask;
  20. import com.punchsettle.server.atomic.entity.User;
  21. import com.punchsettle.server.atomic.service.IPunchInRecordService;
  22. import com.punchsettle.server.atomic.service.IPunchInRecordSettlementRelaService;
  23. import com.punchsettle.server.atomic.service.IPunchInService;
  24. import com.punchsettle.server.atomic.service.IPunchInSettlementService;
  25. import com.punchsettle.server.atomic.service.ISettlementTaskService;
  26. import com.punchsettle.server.atomic.service.IUserService;
  27. import com.punchsettle.server.dto.punchin.PunchInQuery;
  28. import com.punchsettle.server.dto.punchin.PunchInRecordQuery;
  29. import com.punchsettle.server.dto.task.SettleRewardTaskDto;
  30. import com.punchsettle.server.service.manager.ISettleManager;
  31. import com.punchsettle.server.utiis.DateUtils;
  32. import lombok.extern.slf4j.Slf4j;
  33. /**
  34. * @author tyuio
  35. * @version 1.0.0
  36. * @description 结算服务类
  37. * @date 2024/12/12 22:29
  38. */
  39. @Slf4j
  40. @Service
  41. public class SettleManagerImpl implements ISettleManager {
  42. @Autowired
  43. private IPunchInService punchInService;
  44. @Autowired
  45. private IPunchInRecordService punchInRecordService;
  46. @Autowired
  47. private IUserService userService;
  48. @Autowired
  49. private IPunchInSettlementService punchInSettlementService;
  50. @Autowired
  51. private ISettlementTaskService settlementTaskService;
  52. @Autowired
  53. private IPunchInRecordSettlementRelaService punchInRecordSettlementRelaService;
  54. @Override
  55. public void settleReward() {
  56. }
  57. @Override
  58. @Transactional(rollbackFor = Exception.class)
  59. public void settleReward(SettleRewardTaskDto taskDto) {
  60. if (Objects.isNull(taskDto) || Objects.isNull(taskDto.getSettleDate())) {
  61. log.info("结算任务异常,原因:没有指定结算日期");
  62. return;
  63. }
  64. log.info("结算任务开始,结算日期:{}, 结算用户:{}", taskDto.getSettleDate(), taskDto.getUserId());
  65. Timestamp settleStartTime = new Timestamp(System.currentTimeMillis());
  66. // 获取昨天的日期,
  67. LocalDate settleDate = LocalDate.parse(taskDto.getSettleDate());
  68. String settleDateStr = taskDto.getSettleDate();
  69. // 判断是否是周末
  70. boolean weekendFlag =
  71. DayOfWeek.SATURDAY.equals(settleDate.getDayOfWeek()) || DayOfWeek.SUNDAY.equals(settleDate.getDayOfWeek());
  72. boolean sundayFlag = DayOfWeek.SUNDAY.equals(settleDate.getDayOfWeek());
  73. PunchInRecordQuery recordQuery = new PunchInRecordQuery();
  74. recordQuery.setStartDate(settleDateStr);
  75. recordQuery.setEndDate(settleDateStr);
  76. List<PunchInRecord> punchInRecords = punchInRecordService.listByCondition(recordQuery);
  77. if (CollectionUtils.isEmpty(punchInRecords)) {
  78. log.info("结算任务结束,原因:没有打卡记录");
  79. return;
  80. }
  81. List<Long> userIds = punchInRecords.stream().map(PunchInRecord::getCreatedBy).collect(Collectors.toList());
  82. // 读取用户的打卡任务
  83. PunchInQuery punchInQuery = new PunchInQuery();
  84. punchInQuery.setUserIds(userIds);
  85. List<PunchIn> punchIns = punchInService.listByCondition(punchInQuery);
  86. if (CollectionUtils.isEmpty(punchIns)) {
  87. log.info("结算任务结束,原因:根据打卡记录没有找到打卡任务");
  88. return;
  89. }
  90. // 读取用户奖励数据
  91. List<User> users = userService.listByIds(userIds);
  92. if (CollectionUtils.isEmpty(users)) {
  93. log.info("结算任务结束,原因:没有找到用户奖励信息");
  94. return;
  95. }
  96. // 获取一周的打卡记录
  97. Map<Long, List<PunchInRecord>> punchInRecordForWeek = Map.of();
  98. if (sundayFlag) {
  99. List<Long> punchInIds = punchIns.stream().map(PunchIn::getId).collect(Collectors.toList());
  100. PunchInRecordQuery recordForWeekQuery = new PunchInRecordQuery();
  101. recordForWeekQuery.setPunchInIds(punchInIds);
  102. recordForWeekQuery.setStartDate(DateUtils.getLastWeekMondayStr());
  103. recordForWeekQuery.setEndDate(DateUtils.getLastWeekSundayStr());
  104. List<PunchInRecord> punchInRecordForWeeks = punchInRecordService.listByCondition(recordForWeekQuery);
  105. if (!CollectionUtils.isEmpty(punchInRecordForWeeks)) {
  106. punchInRecordForWeek =
  107. punchInRecordForWeeks.stream().collect(Collectors.groupingBy(PunchInRecord::getPunchInId));
  108. }
  109. }
  110. // 打卡任务容器
  111. Map<Long, PunchIn> punchInMap =
  112. punchIns.stream().collect(Collectors.toMap(PunchIn::getId, Function.identity(), (key1, key2) -> key1));
  113. // 用户-打卡记录分组
  114. Map<Long, List<PunchInRecord>> userPunchInRecordMap =
  115. punchInRecords.stream().collect(Collectors.groupingBy(PunchInRecord::getCreatedBy));
  116. // 用户-奖励分组
  117. Map<Long, User> userRewardMap = users.stream()
  118. .collect(Collectors.toMap(User::getId, Function.identity(), (key1, key2) -> key1));
  119. // 先创建结算任务执行记录
  120. SettlementTask settlementTask = new SettlementTask();
  121. settlementTask.setSettleDate(settleDateStr);
  122. settlementTask.setStartTime(settleStartTime);
  123. settlementTask.setProcessedNum(userPunchInRecordMap.size());
  124. settlementTaskService.insert(settlementTask);
  125. // 结算时间
  126. Timestamp settlementTime = new Timestamp(System.currentTimeMillis());
  127. List<PunchInSettlement> addPunchInSettlements = new ArrayList<>();
  128. List<User> updateUsers = new ArrayList<>();
  129. List<PunchInRecordSettlementRela> punchInRecordSettlementRelas = new ArrayList<>();
  130. // 有打卡记录的打卡任务则进行结算
  131. for (Long userId : userPunchInRecordMap.keySet()) {
  132. // 获取用户打卡记录
  133. List<PunchInRecord> punchInRecordList = userPunchInRecordMap.get(userId);
  134. if (CollectionUtils.isEmpty(punchInRecordList)) {
  135. log.info("用户{}没有打卡记录,无须结算", userId);
  136. continue;
  137. }
  138. // 获取用户打卡奖励
  139. User user = userRewardMap.get(userId);
  140. if (Objects.isNull(user)) {
  141. log.info("用户{}没有奖励信息,无法结算", userId);
  142. continue;
  143. }
  144. // 根据打卡记录上的打卡任务ID获取具体的打卡任务信息进行结算
  145. int settleRewardNum = 0;
  146. for (PunchInRecord punchInRecord : punchInRecordList) {
  147. PunchIn punchIn = punchInMap.get(punchInRecord.getPunchInId());
  148. if (Objects.isNull(punchIn)) {
  149. continue;
  150. }
  151. // 周末双倍奖励,否则计算普通奖励
  152. settleRewardNum += weekendFlag ? punchIn.getRewardNum() * 2 : punchIn.getRewardNum();
  153. // 周日计算一次全勤双倍奖励
  154. if (sundayFlag && punchIn.getFullAttendanceFlag()) {
  155. List<PunchInRecord> tempRecordList = punchInRecordForWeek.get(punchInRecord.getPunchInId());
  156. if (!CollectionUtils.isEmpty(tempRecordList) && tempRecordList.size() >= 6) {
  157. settleRewardNum += punchIn.getRewardNum() * 2;
  158. }
  159. }
  160. // 构建结算任务与记录关联信息
  161. PunchInRecordSettlementRela rela = new PunchInRecordSettlementRela();
  162. rela.setRecordId(punchInRecord.getId());
  163. rela.setSettlementId(settlementTask.getId());
  164. punchInRecordSettlementRelas.add(rela);
  165. }
  166. // 计算结算前后,用户奖励数的变化
  167. int beforeSettleRewardNum = user.getUnclaimedRewardNum();
  168. int afterSettleRewardNum = beforeSettleRewardNum + settleRewardNum;
  169. int totalRewardNum = user.getTotalRewardNum() + settleRewardNum;
  170. // 构造结算信息
  171. PunchInSettlement addPunchInSettlement = new PunchInSettlement();
  172. addPunchInSettlement.setSettlementTaskId(settlementTask.getId());
  173. addPunchInSettlement.setUserId(userId);
  174. addPunchInSettlement.setSettleRewardNum(settleRewardNum);
  175. addPunchInSettlement.setSettlementTime(settlementTime);
  176. addPunchInSettlement.setBeforeSettleRewardNum(beforeSettleRewardNum);
  177. addPunchInSettlement.setAfterSettleRewardNum(afterSettleRewardNum);
  178. addPunchInSettlements.add(addPunchInSettlement);
  179. // 构造用户奖励信息
  180. User updateUser = new User();
  181. updateUser.setId(user.getId());
  182. updateUser.setTotalRewardNum(totalRewardNum);
  183. updateUser.setUnclaimedRewardNum(afterSettleRewardNum);
  184. updateUsers.add(updateUser);
  185. }
  186. // 更新用户奖励信息
  187. userService.batchUpdateUser(updateUsers);
  188. // 新增结算信息
  189. punchInSettlementService.batchInsert(addPunchInSettlements);
  190. // 构造并新增关联信息
  191. punchInRecordSettlementRelaService.batchInsert(punchInRecordSettlementRelas);
  192. // 构造并新增结算任务信息
  193. settlementTask.setProcessedSettleNum(addPunchInSettlements.size());
  194. settlementTask
  195. .setProcessedUnsettleNum(settlementTask.getProcessedNum() - settlementTask.getProcessedSettleNum());
  196. settlementTask.setEndTime(new Timestamp(System.currentTimeMillis()));
  197. settlementTaskService.update(settlementTask);
  198. log.info("结算任务结束");
  199. }
  200. }