SettleManagerImpl.java 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482
  1. package com.punchsettle.server.service.manager.impl;
  2. import java.sql.Timestamp;
  3. import java.text.SimpleDateFormat;
  4. import java.time.LocalDate;
  5. import java.time.LocalTime;
  6. import java.util.ArrayList;
  7. import java.util.List;
  8. import java.util.Map;
  9. import java.util.Objects;
  10. import java.util.Optional;
  11. import java.util.function.Function;
  12. import java.util.stream.Collectors;
  13. import org.springframework.beans.BeanUtils;
  14. import org.springframework.beans.factory.annotation.Autowired;
  15. import org.springframework.stereotype.Service;
  16. import org.springframework.transaction.annotation.Transactional;
  17. import org.springframework.util.CollectionUtils;
  18. import com.punchsettle.server.atomic.entity.PunchIn;
  19. import com.punchsettle.server.atomic.entity.PunchInRecord;
  20. import com.punchsettle.server.atomic.entity.PunchInRecordSettlementRela;
  21. import com.punchsettle.server.atomic.entity.PunchInSettlement;
  22. import com.punchsettle.server.atomic.entity.SettlementTask;
  23. import com.punchsettle.server.atomic.entity.User;
  24. import com.punchsettle.server.atomic.service.IPunchInRecordService;
  25. import com.punchsettle.server.atomic.service.IPunchInRecordSettlementRelaService;
  26. import com.punchsettle.server.atomic.service.IPunchInService;
  27. import com.punchsettle.server.atomic.service.IPunchInSettlementService;
  28. import com.punchsettle.server.atomic.service.ISettlementTaskService;
  29. import com.punchsettle.server.atomic.service.IUserService;
  30. import com.punchsettle.server.common.exception.BusinessException;
  31. import com.punchsettle.server.common.utils.Assert;
  32. import com.punchsettle.server.constant.PunchInCategoryEnum;
  33. import com.punchsettle.server.constant.PunchInRuleEnum;
  34. import com.punchsettle.server.constant.PunchInSettleTypeEnum;
  35. import com.punchsettle.server.constant.PunchInStatusEnum;
  36. import com.punchsettle.server.pojo.punchin.PunchInQuery;
  37. import com.punchsettle.server.pojo.punchin.PunchInRecordQuery;
  38. import com.punchsettle.server.pojo.settle.SettleInfoDto;
  39. import com.punchsettle.server.pojo.settle.SettleQuery;
  40. import com.punchsettle.server.pojo.settle.SettleRequest;
  41. import com.punchsettle.server.pojo.settle.SettleResultDto;
  42. import com.punchsettle.server.pojo.settle.SettleVO;
  43. import com.punchsettle.server.service.manager.ISettleManager;
  44. import com.punchsettle.server.utiis.DateUtils;
  45. import com.punchsettle.server.utiis.SpringUtils;
  46. import lombok.extern.slf4j.Slf4j;
  47. /**
  48. * @author tyuio
  49. * @version 1.0.0
  50. * @description 结算服务类
  51. * @date 2024/12/12 22:29
  52. */
  53. @Slf4j
  54. @Service
  55. public class SettleManagerImpl implements ISettleManager {
  56. @Autowired
  57. private IPunchInService punchInService;
  58. @Autowired
  59. private IPunchInRecordService punchInRecordService;
  60. @Autowired
  61. private IUserService userService;
  62. @Autowired
  63. private IPunchInSettlementService punchInSettlementService;
  64. @Autowired
  65. private ISettlementTaskService settlementTaskService;
  66. @Autowired
  67. private IPunchInRecordSettlementRelaService punchInRecordSettlementRelaService;
  68. @Override
  69. @Transactional(rollbackFor = Exception.class)
  70. public void settleHandler(PunchInSettleTypeEnum settleType, LocalDate settleDate, List<Long> userIds, List<Long> punchInIds) {
  71. if (Objects.isNull(settleType)) {
  72. log.info("结算任务异常,原因:没有指定结算类型");
  73. return;
  74. }
  75. if (Objects.isNull(settleDate)) {
  76. log.info("结算任务异常,原因:没有指定结算日期");
  77. return;
  78. }
  79. if (settleDate.isAfter(LocalDate.now())) {
  80. BusinessException.throwFail(String.format("结算任务异常,原因:结算日期{} 不能大于等于今天", settleDate));
  81. }
  82. log.info("结算任务开始,结算类型:{}, 结算日期:{}", settleType.getName(), settleDate);
  83. Timestamp settleStartTime = new Timestamp(System.currentTimeMillis());
  84. SettleInfoDto settleInfo = new SettleInfoDto(settleType, settleDate);
  85. // 读取用户数据,如果userIds为空则结算所有的用户
  86. userIds = Optional.ofNullable(userIds).orElseGet(() -> {
  87. PunchInRecordQuery recordQuery = new PunchInRecordQuery();
  88. recordQuery.setStartDate(settleInfo.getSettleDateStr());
  89. recordQuery.setEndDate(settleInfo.getSettleDateStr());
  90. List<PunchInRecord> punchInRecords = punchInRecordService.listByCondition(recordQuery);
  91. return punchInRecords.stream().map(PunchInRecord::getCreatedBy).collect(Collectors.toList());
  92. });
  93. List<User> users = userService.listByIds(userIds);
  94. if (CollectionUtils.isEmpty(users)) {
  95. log.info("结算任务结束,原因:没有找到待结算的用户信息");
  96. return;
  97. }
  98. // 读取用户的打卡任务,如果punchIds为空则结算用户所有的打卡任务
  99. PunchInQuery punchInQuery = new PunchInQuery();
  100. punchInQuery.setUserIds(userIds);
  101. if (!CollectionUtils.isEmpty(punchInIds)) {
  102. punchInQuery.setPunchInIds(punchInIds);
  103. }
  104. List<PunchIn> punchIns = punchInService.listByCondition(punchInQuery);
  105. if (CollectionUtils.isEmpty(punchIns)) {
  106. log.info("结算任务结束,原因:没有找到打卡任务");
  107. return;
  108. }
  109. // 获取最新的打卡任务ID
  110. punchInIds = punchIns.stream().map(PunchIn::getId).collect(Collectors.toList());
  111. // 获取结算日的打卡记录
  112. PunchInRecordQuery recordQuery = new PunchInRecordQuery();
  113. recordQuery.setStartDate(settleInfo.getSettleDateStr());
  114. recordQuery.setEndDate(settleInfo.getSettleDateStr());
  115. recordQuery.setPunchInIds(punchInIds);
  116. List<PunchInRecord> punchInRecords = punchInRecordService.listByCondition(recordQuery);
  117. if (CollectionUtils.isEmpty(punchInRecords) && !PunchInSettleTypeEnum.REMAKE.equals(settleInfo.getSettleType())) {
  118. log.info("结算任务结束,原因:没有打卡记录");
  119. return;
  120. }
  121. // 获取一周的打卡记录
  122. Map<Long, List<PunchInRecord>> weeklyPunchInRecords = Map.of();
  123. if (settleInfo.getSundayFlag() || PunchInSettleTypeEnum.REMAKE.equals(settleInfo.getSettleType())) {
  124. PunchInRecordQuery weeklyRecordQuery = new PunchInRecordQuery();
  125. weeklyRecordQuery.setPunchInIds(punchInIds);
  126. weeklyRecordQuery.setStartDate(DateUtils.getLastWeekMonday(settleInfo.getSettleDate()).toString());
  127. weeklyRecordQuery.setEndDate(DateUtils.getLastWeekSunday(settleInfo.getSettleDate()).toString());
  128. List<PunchInRecord> punchInRecordForWeeks = punchInRecordService.listByCondition(weeklyRecordQuery);
  129. if (!CollectionUtils.isEmpty(punchInRecordForWeeks)) {
  130. weeklyPunchInRecords = punchInRecordForWeeks.stream().collect(Collectors.groupingBy(PunchInRecord::getPunchInId));
  131. }
  132. }
  133. // 用户-打卡任务分组
  134. Map<Long, List<PunchIn>> userPunchInMap = punchIns.stream().collect(Collectors.groupingBy(PunchIn::getCreatedBy));
  135. // 打卡任务-打卡记录 map
  136. Map<Long, PunchInRecord> punchInRecordMap = punchInRecords.stream().collect(Collectors.toMap(PunchInRecord::getPunchInId, Function.identity(), (key1, key2) -> key1));
  137. // 先创建结算任务执行记录
  138. SettlementTask settlementTask = new SettlementTask();
  139. settlementTask.setSettleDate(settleDate.toString());
  140. settlementTask.setStartTime(settleStartTime);
  141. settlementTask.setProcessedNum(users.size());
  142. settlementTaskService.insert(settlementTask);
  143. // 结算
  144. List<SettleResultDto> settleResultDtoList = new ArrayList<>();
  145. for (User user : users) {
  146. SettleResultDto settleResult = settle(settleInfo, user, userPunchInMap.get(user.getId()), punchInRecordMap, weeklyPunchInRecords);
  147. settleResultDtoList.add(settleResult);
  148. }
  149. // 更新数据
  150. // 待更新的用户
  151. List<User> updateUsers = new ArrayList<>();
  152. // 待更新的打卡记录
  153. List<PunchInRecord> updatePunchInRecords = new ArrayList<>();
  154. // 待新增的打卡记录
  155. List<PunchInRecord> addPunchInRecords = new ArrayList<>();
  156. // 待新增的打卡结算信息
  157. List<PunchInSettlement> addPunchInSettlements = new ArrayList<>();
  158. for (SettleResultDto settleResult : settleResultDtoList) {
  159. updateUsers.add(settleResult.getUpdateUser());
  160. addPunchInRecords.addAll(settleResult.getAddPunchInRecords());
  161. updatePunchInRecords.addAll(settleResult.getUpdatePunchInRecords());
  162. addPunchInSettlements.add(settleResult.getAddPunchInSettlement());
  163. }
  164. // 更新用户奖励信息
  165. if (!CollectionUtils.isEmpty(updateUsers)) {
  166. userService.batchUpdateUser(updateUsers);
  167. }
  168. // 新增打卡记录
  169. if (!CollectionUtils.isEmpty(addPunchInRecords)) {
  170. punchInRecordService.batchInsert(addPunchInRecords);
  171. }
  172. // 更新已有的打卡记录
  173. if (!CollectionUtils.isEmpty(updatePunchInRecords)) {
  174. punchInRecordService.batchUpdate(updatePunchInRecords);
  175. }
  176. // 新增结算信息
  177. if (!CollectionUtils.isEmpty(addPunchInSettlements)) {
  178. // 补充本次的计算任务ID
  179. addPunchInSettlements.stream().forEach(v -> v.setSettlementTaskId(settlementTask.getId()));
  180. punchInSettlementService.batchInsert(addPunchInSettlements);
  181. }
  182. // 新增关联信息
  183. if (!CollectionUtils.isEmpty(settleResultDtoList)) {
  184. List<PunchInRecordSettlementRela> relaList = buildPunchInRecordSettlementRelaList(settleResultDtoList);
  185. if (!CollectionUtils.isEmpty(relaList)) {
  186. punchInRecordSettlementRelaService.batchInsert(relaList);
  187. }
  188. }
  189. // 构造并新增结算任务信息
  190. settlementTask.setProcessedSettleNum(addPunchInSettlements.size());
  191. settlementTask.setProcessedUnsettleNum(settlementTask.getProcessedNum() - settlementTask.getProcessedSettleNum());
  192. settlementTask.setEndTime(new Timestamp(System.currentTimeMillis()));
  193. settlementTaskService.update(settlementTask);
  194. log.info("结算任务结束");
  195. }
  196. /**
  197. * 结算
  198. * @param settleInfo 结算基本信息
  199. * @param user 待结算的用户
  200. * @param punchIns 打卡任务
  201. * @param punchInRecordMap 打卡任务-打卡记录 map
  202. * @param weeklyPunchInRecordMap 打卡任务-一周打卡记录 map
  203. * @return
  204. */
  205. private SettleResultDto settle(SettleInfoDto settleInfo, User user, List<PunchIn> punchIns, Map<Long, PunchInRecord> punchInRecordMap, Map<Long, List<PunchInRecord>> weeklyPunchInRecordMap) {
  206. // 结算奖励数
  207. int settleRewardNum = 0;
  208. // 待更新的打卡记录
  209. List<PunchInRecord> updatePunchInRecords = new ArrayList<>();
  210. // 待新增的打卡记录
  211. List<PunchInRecord> addPunchInRecords = new ArrayList<>();
  212. // 结算
  213. for (PunchIn punchIn : punchIns) {
  214. // 获取打卡记录
  215. PunchInRecord punchInRecord = punchInRecordMap.get(punchIn.getId());
  216. // 不是补打卡且不存在打卡记录直接跳过,无须结算和更新记录状态
  217. if (!PunchInSettleTypeEnum.REMAKE.equals(settleInfo.getSettleType()) && Objects.isNull(punchInRecord)) {
  218. continue;
  219. }
  220. // 判断是否满足打卡规则
  221. PunchInStatusEnum punchInStatus = judgePunchInStatus(punchIn, punchInRecord);
  222. // 不是补卡或打卡任务未完成,则跳过
  223. if (!PunchInSettleTypeEnum.REMAKE.equals(settleInfo.getSettleType()) && PunchInStatusEnum.UN_FINISH.equals(punchInStatus)) {
  224. PunchInRecord updatePunchInRecord = buildPunchInRecordForSettle(punchIn);
  225. updatePunchInRecord.setId(punchInRecord.getId());
  226. updatePunchInRecord.setPunchInStatus(punchInStatus);
  227. updatePunchInRecords.add(updatePunchInRecord);
  228. continue;
  229. }
  230. // 补打卡,完全没有打卡记录则需要补充打卡记录
  231. if (PunchInSettleTypeEnum.REMAKE.equals(settleInfo.getSettleType()) && Objects.isNull(punchInRecord)) {
  232. punchInRecord = buildPunchInRecordForSettle(punchIn);
  233. punchInRecord.setPunchInId(punchIn.getId());
  234. punchInRecord.setPunchInDate(settleInfo.getSettleDateStr());
  235. punchInRecord.setPunchInStatus(PunchInStatusEnum.REMAKE_FINISH);
  236. addPunchInRecords.add(punchInRecord);
  237. }
  238. // 补打卡,已有打卡记录但是不满足打卡规则,则需要对打卡记录做准备
  239. if (PunchInSettleTypeEnum.REMAKE.equals(settleInfo.getSettleType()) && PunchInStatusEnum.UN_FINISH.equals(punchInStatus)) {
  240. fillTrack(punchIn, punchInRecord);
  241. }
  242. // 不是补卡,且打卡状态为完成,需要更新打卡状态为完成
  243. if (Objects.isNull(punchInRecord.getPunchInStatus()) || PunchInStatusEnum.DOING.equals(punchInRecord.getPunchInStatus())) {
  244. PunchInRecord updatePunchInRecord = buildPunchInRecordForSettle(punchIn);
  245. updatePunchInRecord.setId(punchInRecord.getId());
  246. updatePunchInRecord.setPunchInStatus(punchInStatus);
  247. updatePunchInRecords.add(updatePunchInRecord);
  248. }
  249. // 周末双倍奖励,否则计算普通奖励
  250. settleRewardNum += settleInfo.getWeekendFlag() && punchIn.getWeekendDoubleFlag() ? punchIn.getRewardNum() * 2 : punchIn.getRewardNum();
  251. // 计算全勤双倍奖励
  252. if (judgeFullAttendance(settleInfo, punchIn, weeklyPunchInRecordMap)) {
  253. settleRewardNum += punchIn.getRewardNum() * 2;
  254. }
  255. }
  256. // 计算结算前后,用户奖励数的变化
  257. int beforeSettleRewardNum = user.getUnclaimedRewardNum();
  258. int afterSettleRewardNum = beforeSettleRewardNum + settleRewardNum;
  259. int totalRewardNum = user.getTotalRewardNum() + settleRewardNum;
  260. // 构造结算信息
  261. PunchInSettlement addPunchInSettlement = new PunchInSettlement();
  262. addPunchInSettlement.setUserId(user.getId());
  263. addPunchInSettlement.setSettleRewardNum(settleRewardNum);
  264. addPunchInSettlement.setSettlementTime(new Timestamp(System.currentTimeMillis()));
  265. addPunchInSettlement.setBeforeSettleRewardNum(beforeSettleRewardNum);
  266. addPunchInSettlement.setAfterSettleRewardNum(afterSettleRewardNum);
  267. // 构造用户奖励信息
  268. User updateUser = new User();
  269. updateUser.setId(user.getId());
  270. updateUser.setTotalRewardNum(totalRewardNum);
  271. updateUser.setUnclaimedRewardNum(afterSettleRewardNum);
  272. SettleResultDto settleResultDto = new SettleResultDto();
  273. settleResultDto.setUpdateUser(updateUser);
  274. settleResultDto.setAddPunchInRecords(addPunchInRecords);
  275. settleResultDto.setUpdatePunchInRecords(updatePunchInRecords);
  276. settleResultDto.setAddPunchInSettlement(addPunchInSettlement);
  277. return settleResultDto;
  278. }
  279. @Override
  280. public PunchInStatusEnum judgePunchInStatus(PunchIn punchIn, PunchInRecord punchInRecord) {
  281. // 没有打卡记录,直接没完成,包含单次打卡的情况无需额外判断
  282. if (Objects.isNull(punchInRecord)) {
  283. return PunchInStatusEnum.UN_FINISH;
  284. }
  285. // 单次打卡
  286. if (PunchInCategoryEnum.SINGLE.equals(punchIn.getCategory())) {
  287. return PunchInStatusEnum.FINISH;
  288. }
  289. // 计数打卡
  290. if (PunchInCategoryEnum.COUNT.equals(punchIn.getCategory())) {
  291. Integer recordCountTrack = Optional.ofNullable(punchInRecord.getCountTrack()).orElse(0);
  292. if (PunchInRuleEnum.GREATER_OR_EQUAL.equals(punchIn.getRule()) && recordCountTrack.compareTo(punchIn.getCountTrack()) == -1) {
  293. return PunchInStatusEnum.UN_FINISH;
  294. }
  295. if (PunchInRuleEnum.LESS_OR_EQUAL.equals(punchIn.getRule()) && recordCountTrack.compareTo(punchIn.getCountTrack()) == 1) {
  296. return PunchInStatusEnum.UN_FINISH;
  297. }
  298. return PunchInStatusEnum.FINISH;
  299. }
  300. // 计时打卡
  301. if (PunchInCategoryEnum.TIME.equals(punchIn.getCategory())) {
  302. LocalTime recordTimeTrack = Optional.ofNullable(punchInRecord.getTimeTrack()).orElse(LocalTime.parse("00:00:00.000"));
  303. if (PunchInRuleEnum.GREATER_OR_EQUAL.equals(punchIn.getRule()) && recordTimeTrack.compareTo(punchIn.getTimeTrack()) == -1) {
  304. return PunchInStatusEnum.UN_FINISH;
  305. }
  306. if (PunchInRuleEnum.LESS_OR_EQUAL.equals(punchIn.getRule()) && recordTimeTrack.compareTo(punchIn.getTimeTrack()) == 1) {
  307. return PunchInStatusEnum.UN_FINISH;
  308. }
  309. return PunchInStatusEnum.FINISH;
  310. }
  311. return PunchInStatusEnum.UN_FINISH;
  312. }
  313. /**
  314. * 填充打卡记录的记录信息(不用考虑单次打卡的情况)
  315. * @param punchIn
  316. * @param punchInRecord
  317. */
  318. private void fillTrack(PunchIn punchIn, PunchInRecord punchInRecord) {
  319. // 计数打卡
  320. if (PunchInCategoryEnum.COUNT.equals(punchIn.getCategory())) {
  321. if (PunchInRuleEnum.GREATER_OR_EQUAL.equals(punchIn.getRule())) {
  322. punchInRecord.setCountTrack(punchIn.getCountTrack() + 1);
  323. }
  324. if (PunchInRuleEnum.LESS_OR_EQUAL.equals(punchIn.getRule())){
  325. punchInRecord.setCountTrack(punchIn.getCountTrack() - 1);
  326. }
  327. }
  328. // 计时打卡
  329. if (PunchInCategoryEnum.TIME.equals(punchIn.getCategory())) {
  330. if (PunchInRuleEnum.GREATER_OR_EQUAL.equals(punchIn.getRule())) {
  331. punchInRecord.setTimeTrack(punchIn.getTimeTrack().plusSeconds(1));
  332. }
  333. if (PunchInRuleEnum.LESS_OR_EQUAL.equals(punchIn.getRule())){
  334. punchInRecord.setTimeTrack(punchIn.getTimeTrack().minusSeconds(1));
  335. }
  336. }
  337. }
  338. /**
  339. * 判断是否进行全勤结算
  340. * @param settleInfo 结算信息
  341. * @param punchIn 打卡任务
  342. * @param weeklyPunchInRecordMap 一周打卡记录
  343. * @return true-
  344. */
  345. private boolean judgeFullAttendance(SettleInfoDto settleInfo, PunchIn punchIn, Map<Long, List<PunchInRecord>> weeklyPunchInRecordMap) {
  346. // 没有启用全勤奖励则跳过
  347. if (!punchIn.getFullAttendanceFlag()) {
  348. return false;
  349. }
  350. // 不是周日结算或者补打卡则跳过,
  351. if (!settleInfo.getSundayFlag() && !PunchInSettleTypeEnum.REMAKE.equals(settleInfo.getSettleType())) {
  352. return false;
  353. }
  354. // 获取一周的完成打卡的打卡记录,并且要排除结算日这天的记录
  355. List<PunchInRecord> weeklyFinishRecord = Optional.ofNullable(weeklyPunchInRecordMap.get(punchIn.getId())).orElse(new ArrayList<>())
  356. .stream().filter(record -> !settleInfo.getSettleDateStr().equals(record.getPunchInDate()) && (PunchInStatusEnum.FINISH.equals(record.getPunchInStatus()) || PunchInStatusEnum.REMAKE_FINISH.equals(record.getPunchInStatus())))
  357. .collect(Collectors.toList());
  358. // 1个是容错允许不打卡或未完成打卡,1个是当天的结算打卡来到这段逻辑就认为已经完成打卡,因此只要有5个完成打卡,则认为全勤
  359. return weeklyFinishRecord.size() >= 5;
  360. }
  361. /**
  362. * 构建待更新结算数据的打卡记录
  363. * @return
  364. */
  365. private PunchInRecord buildPunchInRecordForSettle(PunchIn punchIn) {
  366. PunchInRecord updatePunchInRecord = new PunchInRecord();
  367. updatePunchInRecord.setSettleRewardNum(punchIn.getRewardNum());
  368. updatePunchInRecord.setSettleCategory(punchIn.getCategory());
  369. updatePunchInRecord.setSettleRule(punchIn.getRule());
  370. updatePunchInRecord.setSettleCountTrack(punchIn.getCountTrack());
  371. updatePunchInRecord.setSettleTimeTrack(punchIn.getTimeTrack());
  372. return updatePunchInRecord;
  373. }
  374. /**
  375. * 构造打卡记录与结算记录的关联关系
  376. * @param settleResultDtos
  377. * @return
  378. */
  379. private static List<PunchInRecordSettlementRela> buildPunchInRecordSettlementRelaList(List<SettleResultDto> settleResultDtos) {
  380. if (CollectionUtils.isEmpty(settleResultDtos)) {
  381. return List.of();
  382. }
  383. List<PunchInRecordSettlementRela> relaList = new ArrayList();
  384. // 补充关联关系ID(结算记录ID、打卡记录ID)
  385. for (SettleResultDto settleResultDto : settleResultDtos) {
  386. for (PunchInRecord punchInRecord : settleResultDto.getAddPunchInRecords()) {
  387. PunchInRecordSettlementRela rela = new PunchInRecordSettlementRela();
  388. rela.setRecordId(punchInRecord.getId());
  389. rela.setSettlementId(settleResultDto.getAddPunchInSettlement().getId());
  390. relaList.add(rela);
  391. }
  392. for (PunchInRecord punchInRecord : settleResultDto.getUpdatePunchInRecords()) {
  393. PunchInRecordSettlementRela rela = new PunchInRecordSettlementRela();
  394. rela.setRecordId(punchInRecord.getId());
  395. rela.setSettlementId(settleResultDto.getAddPunchInSettlement().getId());
  396. relaList.add(rela);
  397. }
  398. }
  399. return relaList;
  400. }
  401. @Override
  402. public void manualSettle(SettleRequest settleRequest) {
  403. // TODO 这里考虑加判断条件防止重复手动结算
  404. Assert.isNullInBusiness(settleRequest, "结算请求不能为空");
  405. if (!PunchInSettleTypeEnum.OPS.equals(settleRequest.getSettleType())) {
  406. BusinessException.throwFail("非运维结算,禁止执行");
  407. }
  408. SpringUtils.getBean(ISettleManager.class).settleHandler(settleRequest.getSettleType(), LocalDate.parse(settleRequest.getSettleDate()), settleRequest.getUserIds(), settleRequest.getPunchInIds());
  409. }
  410. @Override
  411. public List<SettleVO> querySettle(SettleQuery query) {
  412. SimpleDateFormat sdf = DateUtils.buildDateTimeFormat();
  413. List<PunchInSettlement> punchInSettlements = punchInSettlementService.listByCondition(query);
  414. return punchInSettlements.stream().map(settlement -> {
  415. SettleVO settleVO = new SettleVO();
  416. BeanUtils.copyProperties(settlement, settleVO);
  417. settleVO.setSettlementTime(sdf.format(settlement.getSettlementTime()));
  418. return settleVO;
  419. }).toList();
  420. }
  421. }