|
@@ -7,9 +7,23 @@ import java.util.ArrayList;
|
|
|
import java.util.List;
|
|
import java.util.List;
|
|
|
import java.util.Map;
|
|
import java.util.Map;
|
|
|
import java.util.Objects;
|
|
import java.util.Objects;
|
|
|
|
|
+import java.util.Optional;
|
|
|
import java.util.function.Function;
|
|
import java.util.function.Function;
|
|
|
import java.util.stream.Collectors;
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
|
|
|
|
+import com.punchsettle.server.common.exception.BusinessException;
|
|
|
|
|
+import com.punchsettle.server.common.utils.Assert;
|
|
|
|
|
+import com.punchsettle.server.constant.PunchInCategoryEnum;
|
|
|
|
|
+import com.punchsettle.server.constant.PunchInRuleEnum;
|
|
|
|
|
+import com.punchsettle.server.constant.PunchInSettleTypeEnum;
|
|
|
|
|
+import com.punchsettle.server.constant.PunchInStatusEnum;
|
|
|
|
|
+import com.punchsettle.server.dto.settle.SettleDto;
|
|
|
|
|
+import com.punchsettle.server.dto.settle.SettleInfoDto;
|
|
|
|
|
+import com.punchsettle.server.dto.settle.SettleQuery;
|
|
|
|
|
+import com.punchsettle.server.dto.settle.SettleRequest;
|
|
|
|
|
+import com.punchsettle.server.dto.settle.SettleResultDto;
|
|
|
|
|
+import com.punchsettle.server.utiis.SpringUtils;
|
|
|
|
|
+import org.springframework.beans.BeanUtils;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.stereotype.Service;
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
@@ -34,6 +48,7 @@ import com.punchsettle.server.service.manager.ISettleManager;
|
|
|
import com.punchsettle.server.utiis.DateUtils;
|
|
import com.punchsettle.server.utiis.DateUtils;
|
|
|
|
|
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
|
|
+import org.springframework.util.StringUtils;
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
|
* @author tyuio
|
|
* @author tyuio
|
|
@@ -63,176 +78,358 @@ public class SettleManagerImpl implements ISettleManager {
|
|
|
@Autowired
|
|
@Autowired
|
|
|
private IPunchInRecordSettlementRelaService punchInRecordSettlementRelaService;
|
|
private IPunchInRecordSettlementRelaService punchInRecordSettlementRelaService;
|
|
|
|
|
|
|
|
- @Override
|
|
|
|
|
- public void settleReward() {
|
|
|
|
|
-
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
@Override
|
|
@Override
|
|
|
@Transactional(rollbackFor = Exception.class)
|
|
@Transactional(rollbackFor = Exception.class)
|
|
|
- public void settleReward(SettleRewardTaskDto taskDto) {
|
|
|
|
|
- if (Objects.isNull(taskDto) || Objects.isNull(taskDto.getSettleDate())) {
|
|
|
|
|
|
|
+ public void settleHandler(PunchInSettleTypeEnum settleType, LocalDate settleDate, List<Long> userIds, List<Long> punchInIds) {
|
|
|
|
|
+ if (Objects.isNull(settleType)) {
|
|
|
|
|
+ log.info("结算任务异常,原因:没有指定结算类型");
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (Objects.isNull(settleDate)) {
|
|
|
log.info("结算任务异常,原因:没有指定结算日期");
|
|
log.info("结算任务异常,原因:没有指定结算日期");
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- log.info("结算任务开始,结算日期:{}, 结算用户:{}", taskDto.getSettleDate(), taskDto.getUserId());
|
|
|
|
|
|
|
+ if (settleDate.isAfter(LocalDate.now())) {
|
|
|
|
|
+ BusinessException.throwFail(String.format("结算任务异常,原因:结算日期{} 不能大于等于今天", settleDate));
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
|
|
+ log.info("结算任务开始,结算类型:{}, 结算日期:{}", settleType.getName(), settleDate);
|
|
|
Timestamp settleStartTime = new Timestamp(System.currentTimeMillis());
|
|
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());
|
|
|
|
|
|
|
+ SettleInfoDto settleInfo = new SettleInfoDto(settleType, settleDate);
|
|
|
|
|
|
|
|
- PunchInRecordQuery recordQuery = new PunchInRecordQuery();
|
|
|
|
|
- recordQuery.setStartDate(settleDateStr);
|
|
|
|
|
- recordQuery.setEndDate(settleDateStr);
|
|
|
|
|
- List<PunchInRecord> punchInRecords = punchInRecordService.listByCondition(recordQuery);
|
|
|
|
|
- if (CollectionUtils.isEmpty(punchInRecords)) {
|
|
|
|
|
- log.info("结算任务结束,原因:没有打卡记录");
|
|
|
|
|
|
|
+ // 读取用户数据,如果userIds为空则结算所有的用户
|
|
|
|
|
+ userIds = Optional.ofNullable(userIds).orElseGet(() -> {
|
|
|
|
|
+ PunchInRecordQuery recordQuery = new PunchInRecordQuery();
|
|
|
|
|
+ recordQuery.setStartDate(settleInfo.getSettleDateStr());
|
|
|
|
|
+ recordQuery.setEndDate(settleInfo.getSettleDateStr());
|
|
|
|
|
+ List<PunchInRecord> punchInRecords = punchInRecordService.listByCondition(recordQuery);
|
|
|
|
|
+ return punchInRecords.stream().map(PunchInRecord::getCreatedBy).collect(Collectors.toList());
|
|
|
|
|
+ });
|
|
|
|
|
+ List<User> users = userService.listByIds(userIds);
|
|
|
|
|
+ if (CollectionUtils.isEmpty(users)) {
|
|
|
|
|
+ log.info("结算任务结束,原因:没有找到待结算的用户信息");
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- List<Long> userIds = punchInRecords.stream().map(PunchInRecord::getCreatedBy).collect(Collectors.toList());
|
|
|
|
|
-
|
|
|
|
|
- // 读取用户的打卡任务
|
|
|
|
|
|
|
+ // 读取用户的打卡任务,如果punchIds为空则结算用户所有的打卡任务
|
|
|
PunchInQuery punchInQuery = new PunchInQuery();
|
|
PunchInQuery punchInQuery = new PunchInQuery();
|
|
|
punchInQuery.setUserIds(userIds);
|
|
punchInQuery.setUserIds(userIds);
|
|
|
|
|
+ punchInQuery.setPunchInIds(punchInIds);
|
|
|
List<PunchIn> punchIns = punchInService.listByCondition(punchInQuery);
|
|
List<PunchIn> punchIns = punchInService.listByCondition(punchInQuery);
|
|
|
if (CollectionUtils.isEmpty(punchIns)) {
|
|
if (CollectionUtils.isEmpty(punchIns)) {
|
|
|
- log.info("结算任务结束,原因:根据打卡记录没有找到打卡任务");
|
|
|
|
|
|
|
+ log.info("结算任务结束,原因:没有找到打卡任务");
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
|
|
|
+ // 获取最新的打卡任务ID
|
|
|
|
|
+ punchInIds = punchIns.stream().map(PunchIn::getId).collect(Collectors.toList());
|
|
|
|
|
|
|
|
- // 读取用户奖励数据
|
|
|
|
|
- List<User> users = userService.listByIds(userIds);
|
|
|
|
|
- if (CollectionUtils.isEmpty(users)) {
|
|
|
|
|
- log.info("结算任务结束,原因:没有找到用户奖励信息");
|
|
|
|
|
|
|
+ // 获取结算日的打卡记录
|
|
|
|
|
+ PunchInRecordQuery recordQuery = new PunchInRecordQuery();
|
|
|
|
|
+ recordQuery.setStartDate(settleInfo.getSettleDateStr());
|
|
|
|
|
+ recordQuery.setEndDate(settleInfo.getSettleDateStr());
|
|
|
|
|
+ recordQuery.setPunchInIds(punchInIds);
|
|
|
|
|
+ List<PunchInRecord> punchInRecords = punchInRecordService.listByCondition(recordQuery);
|
|
|
|
|
+ if (CollectionUtils.isEmpty(punchInRecords)) {
|
|
|
|
|
+ log.info("结算任务结束,原因:没有打卡记录");
|
|
|
return;
|
|
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);
|
|
|
|
|
|
|
+ Map<Long, List<PunchInRecord>> weeklyPunchInRecords = Map.of();
|
|
|
|
|
+ if (settleInfo.getSundayFlag() || PunchInSettleTypeEnum.REMAKE.equals(settleInfo.getSettleType())) {
|
|
|
|
|
+ PunchInRecordQuery weeklyRecordQuery = new PunchInRecordQuery();
|
|
|
|
|
+ weeklyRecordQuery.setPunchInIds(punchInIds);
|
|
|
|
|
+ weeklyRecordQuery.setStartDate(DateUtils.getLastWeekMonday(settleInfo.getSettleDate()).toString());
|
|
|
|
|
+ weeklyRecordQuery.setEndDate(DateUtils.getLastWeekSunday(settleInfo.getSettleDate()).toString());
|
|
|
|
|
+ List<PunchInRecord> punchInRecordForWeeks = punchInRecordService.listByCondition(weeklyRecordQuery);
|
|
|
if (!CollectionUtils.isEmpty(punchInRecordForWeeks)) {
|
|
if (!CollectionUtils.isEmpty(punchInRecordForWeeks)) {
|
|
|
- punchInRecordForWeek =
|
|
|
|
|
- punchInRecordForWeeks.stream().collect(Collectors.groupingBy(PunchInRecord::getPunchInId));
|
|
|
|
|
|
|
+ weeklyPunchInRecords = 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<PunchIn>> userPunchInMap = punchIns.stream().collect(Collectors.groupingBy(PunchIn::getCreatedBy));
|
|
|
|
|
+ // 打卡任务-打卡记录 map
|
|
|
|
|
+ Map<Long, PunchInRecord> punchInRecordMap = punchInRecords.stream().collect(Collectors.toMap(PunchInRecord::getPunchInId, 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));
|
|
|
|
|
|
|
+ // 待更新的用户
|
|
|
|
|
+ List<User> updateUsers = new ArrayList<>();
|
|
|
|
|
+ // 新增的打卡结算关联关系
|
|
|
|
|
+ List<PunchInRecordSettlementRela> addRelas = new ArrayList<>();
|
|
|
|
|
+ // 待更新的打卡记录
|
|
|
|
|
+ List<PunchInRecord> updatePunchInRecords = new ArrayList<>();
|
|
|
|
|
+ // 待新增的打卡记录
|
|
|
|
|
+ List<PunchInRecord> addPunchInRecords = new ArrayList<>();
|
|
|
|
|
+ // 待新增的打卡结算信息
|
|
|
|
|
+ List<PunchInSettlement> addPunchInSettlements = new ArrayList<>();
|
|
|
|
|
|
|
|
// 先创建结算任务执行记录
|
|
// 先创建结算任务执行记录
|
|
|
SettlementTask settlementTask = new SettlementTask();
|
|
SettlementTask settlementTask = new SettlementTask();
|
|
|
- settlementTask.setSettleDate(settleDateStr);
|
|
|
|
|
|
|
+ settlementTask.setSettleDate(settleDate.toString());
|
|
|
settlementTask.setStartTime(settleStartTime);
|
|
settlementTask.setStartTime(settleStartTime);
|
|
|
- settlementTask.setProcessedNum(userPunchInRecordMap.size());
|
|
|
|
|
|
|
+ settlementTask.setProcessedNum(users.size());
|
|
|
settlementTaskService.insert(settlementTask);
|
|
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);
|
|
|
|
|
|
|
+ // 结算
|
|
|
|
|
+ for (User user : users) {
|
|
|
|
|
+ SettleResultDto settleResult = settle(settleInfo, user, userPunchInMap.get(user.getId()), punchInRecordMap, weeklyPunchInRecords);
|
|
|
|
|
+ updateUsers.add(settleResult.getUpdateUser());
|
|
|
|
|
+ addRelas.addAll(settleResult.getAddRelas());
|
|
|
|
|
+ addPunchInRecords.addAll(settleResult.getAddPunchInRecords());
|
|
|
|
|
+ updatePunchInRecords.addAll(settleResult.getUpdatePunchInRecords());
|
|
|
|
|
+ addPunchInSettlements.add(settleResult.getAddPunchInSettlements());
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 更新用户奖励信息
|
|
// 更新用户奖励信息
|
|
|
- userService.batchUpdateUser(updateUsers);
|
|
|
|
|
|
|
+ if (!CollectionUtils.isEmpty(updateUsers)) {
|
|
|
|
|
+ userService.batchUpdateUser(updateUsers);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 新增打卡记录
|
|
|
|
|
+ if (!CollectionUtils.isEmpty(addPunchInRecords)) {
|
|
|
|
|
+ punchInRecordService.batchInsert(addPunchInRecords);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if (!CollectionUtils.isEmpty(updatePunchInRecords)) {
|
|
|
|
|
+ punchInRecordService.batchUpdate(updatePunchInRecords);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
// 新增结算信息
|
|
// 新增结算信息
|
|
|
- punchInSettlementService.batchInsert(addPunchInSettlements);
|
|
|
|
|
|
|
+ if (!CollectionUtils.isEmpty(addPunchInSettlements)) {
|
|
|
|
|
+ punchInSettlementService.batchInsert(addPunchInSettlements);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- // 构造并新增关联信息
|
|
|
|
|
- punchInRecordSettlementRelaService.batchInsert(punchInRecordSettlementRelas);
|
|
|
|
|
|
|
+ // 新增关联信息
|
|
|
|
|
+ if (!CollectionUtils.isEmpty(addRelas)) {
|
|
|
|
|
+ punchInRecordSettlementRelaService.batchInsert(addRelas);
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
// 构造并新增结算任务信息
|
|
// 构造并新增结算任务信息
|
|
|
settlementTask.setProcessedSettleNum(addPunchInSettlements.size());
|
|
settlementTask.setProcessedSettleNum(addPunchInSettlements.size());
|
|
|
- settlementTask
|
|
|
|
|
- .setProcessedUnsettleNum(settlementTask.getProcessedNum() - settlementTask.getProcessedSettleNum());
|
|
|
|
|
|
|
+ settlementTask.setProcessedUnsettleNum(settlementTask.getProcessedNum() - settlementTask.getProcessedSettleNum());
|
|
|
settlementTask.setEndTime(new Timestamp(System.currentTimeMillis()));
|
|
settlementTask.setEndTime(new Timestamp(System.currentTimeMillis()));
|
|
|
settlementTaskService.update(settlementTask);
|
|
settlementTaskService.update(settlementTask);
|
|
|
|
|
|
|
|
log.info("结算任务结束");
|
|
log.info("结算任务结束");
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 结算
|
|
|
|
|
+ * @param settleInfo 结算基本信息
|
|
|
|
|
+ * @param user 待结算的用户
|
|
|
|
|
+ * @param punchIns 打卡任务
|
|
|
|
|
+ * @param punchInRecordMap 打卡任务-打卡记录 map
|
|
|
|
|
+ * @param weeklyPunchInRecordMap 打卡任务-一周打卡记录 map
|
|
|
|
|
+ * @return
|
|
|
|
|
+ */
|
|
|
|
|
+ private SettleResultDto settle(SettleInfoDto settleInfo, User user, List<PunchIn> punchIns, Map<Long, PunchInRecord> punchInRecordMap, Map<Long, List<PunchInRecord>> weeklyPunchInRecordMap) {
|
|
|
|
|
+ // 结算奖励数
|
|
|
|
|
+ int settleRewardNum = 0;
|
|
|
|
|
+ // 新增的打卡结算关联关系
|
|
|
|
|
+ List<PunchInRecordSettlementRela> addRelas = new ArrayList<>();
|
|
|
|
|
+ // 待更新的打卡记录
|
|
|
|
|
+ List<PunchInRecord> updatePunchInRecords = new ArrayList<>();
|
|
|
|
|
+ // 待新增的打卡记录
|
|
|
|
|
+ List<PunchInRecord> addPunchInRecords = new ArrayList<>();
|
|
|
|
|
+ // 结算
|
|
|
|
|
+ for (PunchIn punchIn : punchIns) {
|
|
|
|
|
+ // 获取打卡记录
|
|
|
|
|
+ PunchInRecord punchInRecord = punchInRecordMap.get(punchIn.getId());
|
|
|
|
|
+ // 判断是否满足打卡规则
|
|
|
|
|
+ PunchInStatusEnum punchInStatus = judgePunchInStatus(punchIn, punchInRecord);
|
|
|
|
|
+ //不满足则跳过无需接续,如果是补卡则直接完成继续计算
|
|
|
|
|
+ if (!PunchInSettleTypeEnum.REMAKE.equals(settleInfo.getSettleType()) && PunchInStatusEnum.UN_FINISH.equals(punchInStatus)) {
|
|
|
|
|
+ punchInRecord.setPunchInStatus(punchInStatus);
|
|
|
|
|
+ updatePunchInRecords.add(punchInRecord);
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 补打卡,完全没有打卡记录则需要补充打卡记录
|
|
|
|
|
+ if (PunchInSettleTypeEnum.REMAKE.equals(settleInfo.getSettleType()) && Objects.isNull(punchInRecord)) {
|
|
|
|
|
+ punchInRecord = new PunchInRecord();
|
|
|
|
|
+ punchInRecord.setPunchInId(punchIn.getId());
|
|
|
|
|
+ punchInRecord.setPunchInDate(settleInfo.getSettleDateStr());
|
|
|
|
|
+ addPunchInRecords.add(punchInRecord);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 补打卡,已有打卡记录但是不满足打卡规则,则需要对打卡记录做准备
|
|
|
|
|
+ if (PunchInSettleTypeEnum.REMAKE.equals(settleInfo.getSettleType()) && PunchInStatusEnum.UN_FINISH.equals(punchInStatus)) {
|
|
|
|
|
+ punchInRecord.setPunchInStatus(PunchInStatusEnum.REMAKE_FINISH);
|
|
|
|
|
+ fillTrack(punchIn, punchInRecord);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 周末双倍奖励,否则计算普通奖励
|
|
|
|
|
+ settleRewardNum += settleInfo.getWeekendFlag() ? punchIn.getRewardNum() * 2 : punchIn.getRewardNum();
|
|
|
|
|
+ // 计算全勤双倍奖励
|
|
|
|
|
+ if (judgeFullAttendance(settleInfo, punchIn, weeklyPunchInRecordMap)) {
|
|
|
|
|
+ settleRewardNum += punchIn.getRewardNum() * 2;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 构建结算任务与记录关联信息
|
|
|
|
|
+ PunchInRecordSettlementRela rela = new PunchInRecordSettlementRela();
|
|
|
|
|
+ rela.setRecordId(punchInRecord.getId());
|
|
|
|
|
+ rela.setRewardNum(punchIn.getRewardNum());
|
|
|
|
|
+ rela.setCategory(punchIn.getCategory());
|
|
|
|
|
+ rela.setRule(punchIn.getRule());
|
|
|
|
|
+ addRelas.add(rela);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 计算结算前后,用户奖励数的变化
|
|
|
|
|
+ int beforeSettleRewardNum = user.getUnclaimedRewardNum();
|
|
|
|
|
+ int afterSettleRewardNum = beforeSettleRewardNum + settleRewardNum;
|
|
|
|
|
+ int totalRewardNum = user.getTotalRewardNum() + settleRewardNum;
|
|
|
|
|
+
|
|
|
|
|
+ // 构造结算信息
|
|
|
|
|
+ PunchInSettlement addPunchInSettlement = new PunchInSettlement();
|
|
|
|
|
+ addPunchInSettlement.setUserId(user.getId());
|
|
|
|
|
+ addPunchInSettlement.setSettleRewardNum(settleRewardNum);
|
|
|
|
|
+ addPunchInSettlement.setSettlementTime(new Timestamp(System.currentTimeMillis()));
|
|
|
|
|
+ addPunchInSettlement.setBeforeSettleRewardNum(beforeSettleRewardNum);
|
|
|
|
|
+ addPunchInSettlement.setAfterSettleRewardNum(afterSettleRewardNum);
|
|
|
|
|
+
|
|
|
|
|
+ // 构造用户奖励信息
|
|
|
|
|
+ User updateUser = new User();
|
|
|
|
|
+ updateUser.setId(user.getId());
|
|
|
|
|
+ updateUser.setTotalRewardNum(totalRewardNum);
|
|
|
|
|
+ updateUser.setUnclaimedRewardNum(afterSettleRewardNum);
|
|
|
|
|
+
|
|
|
|
|
+ SettleResultDto settleResultDto = new SettleResultDto();
|
|
|
|
|
+ settleResultDto.setAddRelas(addRelas);
|
|
|
|
|
+ settleResultDto.setUpdateUser(updateUser);
|
|
|
|
|
+ settleResultDto.setAddPunchInRecords(addPunchInRecords);
|
|
|
|
|
+ settleResultDto.setUpdatePunchInRecords(updatePunchInRecords);
|
|
|
|
|
+ settleResultDto.setAddPunchInSettlements(addPunchInSettlement);
|
|
|
|
|
+ return settleResultDto;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 判断是否满足打卡规则完成打卡
|
|
|
|
|
+ * @param punchIn
|
|
|
|
|
+ * @param punchInRecord
|
|
|
|
|
+ * @return PunchInStatusEnum
|
|
|
|
|
+ */
|
|
|
|
|
+ private PunchInStatusEnum judgePunchInStatus(PunchIn punchIn, PunchInRecord punchInRecord) {
|
|
|
|
|
+ // 没有打卡记录,直接没完成,包含单次打卡的情况无需额外判断
|
|
|
|
|
+ if (Objects.isNull(punchInRecord)) {
|
|
|
|
|
+ return PunchInStatusEnum.UN_FINISH;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 计数打卡
|
|
|
|
|
+ if (PunchInCategoryEnum.COUNT.equals(punchIn.getCategory())) {
|
|
|
|
|
+ if (PunchInRuleEnum.GREATER.equals(punchIn.getRule()) && punchInRecord.getCountTrack().compareTo(punchIn.getCountTrack()) < 1) {
|
|
|
|
|
+ return PunchInStatusEnum.UN_FINISH;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (PunchInRuleEnum.GREATER_OR_EQUAL.equals(punchIn.getRule()) && punchInRecord.getCountTrack().compareTo(punchIn.getCountTrack()) == -1) {
|
|
|
|
|
+ return PunchInStatusEnum.UN_FINISH;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (PunchInRuleEnum.LESS.equals(punchIn.getRule()) && punchInRecord.getCountTrack().compareTo(punchIn.getCountTrack()) > -1) {
|
|
|
|
|
+ return PunchInStatusEnum.UN_FINISH;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (PunchInRuleEnum.LESS_OR_EQUAL.equals(punchIn.getRule()) && punchInRecord.getCountTrack().compareTo(punchIn.getCountTrack()) == 1) {
|
|
|
|
|
+ return PunchInStatusEnum.UN_FINISH;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return PunchInStatusEnum.FINISH;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 计时打卡
|
|
|
|
|
+ if (PunchInCategoryEnum.TIME.equals(punchIn.getCategory())) {
|
|
|
|
|
+ if (PunchInRuleEnum.GREATER.equals(punchIn.getRule()) && punchInRecord.getTimeTrack().compareTo(punchIn.getTimeTrack()) < 1) {
|
|
|
|
|
+ return PunchInStatusEnum.UN_FINISH;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (PunchInRuleEnum.GREATER_OR_EQUAL.equals(punchIn.getRule()) && punchInRecord.getTimeTrack().compareTo(punchIn.getTimeTrack()) == -1) {
|
|
|
|
|
+ return PunchInStatusEnum.UN_FINISH;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (PunchInRuleEnum.LESS.equals(punchIn.getRule()) && punchInRecord.getTimeTrack().compareTo(punchIn.getTimeTrack()) > -1) {
|
|
|
|
|
+ return PunchInStatusEnum.UN_FINISH;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (PunchInRuleEnum.LESS_OR_EQUAL.equals(punchIn.getRule()) && punchInRecord.getTimeTrack().compareTo(punchIn.getTimeTrack()) == 1) {
|
|
|
|
|
+ return PunchInStatusEnum.UN_FINISH;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return PunchInStatusEnum.FINISH;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ return PunchInStatusEnum.UN_FINISH;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 填充打卡记录的记录信息(不用考虑单次打卡的情况)
|
|
|
|
|
+ * @param punchIn
|
|
|
|
|
+ * @param punchInRecord
|
|
|
|
|
+ */
|
|
|
|
|
+ private void fillTrack(PunchIn punchIn, PunchInRecord punchInRecord) {
|
|
|
|
|
+ // 计数打卡
|
|
|
|
|
+ if (PunchInCategoryEnum.COUNT.equals(punchIn.getCategory())) {
|
|
|
|
|
+ if (PunchInRuleEnum.GREATER.equals(punchIn.getRule())) {
|
|
|
|
|
+ punchInRecord.setCountTrack(punchIn.getCountTrack() + 1);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (PunchInRuleEnum.LESS.equals(punchIn.getRule())){
|
|
|
|
|
+ punchInRecord.setCountTrack(punchIn.getCountTrack() - 1);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 计时打卡
|
|
|
|
|
+ if (PunchInCategoryEnum.TIME.equals(punchIn.getCategory())) {
|
|
|
|
|
+ if (PunchInRuleEnum.GREATER.equals(punchIn.getRule())) {
|
|
|
|
|
+ punchInRecord.setTimeTrack(punchIn.getTimeTrack().plusSeconds(1));
|
|
|
|
|
+ }
|
|
|
|
|
+ if (PunchInRuleEnum.LESS.equals(punchIn.getRule())){
|
|
|
|
|
+ punchInRecord.setTimeTrack(punchIn.getTimeTrack().minusSeconds(1));
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 判断是否进行全勤结算
|
|
|
|
|
+ * @param settleInfo 结算信息
|
|
|
|
|
+ * @param punchIn 打卡任务
|
|
|
|
|
+ * @param weeklyPunchInRecordMap 一周打卡记录
|
|
|
|
|
+ * @return true-
|
|
|
|
|
+ */
|
|
|
|
|
+ private boolean judgeFullAttendance(SettleInfoDto settleInfo, PunchIn punchIn, Map<Long, List<PunchInRecord>> weeklyPunchInRecordMap) {
|
|
|
|
|
+ // 没有启用全勤奖励则跳过
|
|
|
|
|
+ if (!punchIn.getFullAttendanceFlag()) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 不是周日结算或者补打卡则跳过,
|
|
|
|
|
+ if (!settleInfo.getSundayFlag() && !PunchInSettleTypeEnum.REMAKE.equals(settleInfo.getSettleType())) {
|
|
|
|
|
+ return false;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 获取一周的完成打卡的打卡记录,并且要排除结算日这天的记录
|
|
|
|
|
+ List<PunchInRecord> weeklyFinishRecord = Optional.ofNullable(weeklyPunchInRecordMap.get(punchIn.getId())).orElse(new ArrayList<>())
|
|
|
|
|
+ .stream().filter(record -> !settleInfo.getSettleDateStr().equals(record.getPunchInDate()) && (PunchInStatusEnum.FINISH.equals(record.getPunchInStatus()) || PunchInStatusEnum.REMAKE_FINISH.equals(record.getPunchInStatus())))
|
|
|
|
|
+ .collect(Collectors.toList());
|
|
|
|
|
+
|
|
|
|
|
+ // 1个是容错允许不打卡或未完成打卡,1个是当天的结算打卡来到这段逻辑就认为已经完成打卡,因此只要有5个完成打卡,则认为全勤
|
|
|
|
|
+ return weeklyFinishRecord.size() >= 5;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public void manualSettle(SettleRequest settleRequest) {
|
|
|
|
|
+ Assert.isNullInBusiness(settleRequest, "结算请求不能为空");
|
|
|
|
|
+ SpringUtils.getBean(ISettleManager.class).settleHandler(settleRequest.getSettleType(), LocalDate.parse(settleRequest.getSettleDate()), settleRequest.getUserIds(), settleRequest.getPunchInIds());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public List<SettleDto> querySettle(SettleQuery query) {
|
|
|
|
|
+ if (Objects.isNull(query) || !StringUtils.hasText(query.getStartDate()) || !StringUtils.hasText(query.getEndDate())) {
|
|
|
|
|
+ BusinessException.throwFail("请选择待查询的结算记录时间范围");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ query.setStartDate(String.format("%s 00:00:00.000", query.getStartDate()));
|
|
|
|
|
+ query.setEndDate(String.format("%s 23:59:59.999", query.getEndDate()));
|
|
|
|
|
+
|
|
|
|
|
+ List<PunchInSettlement> punchInSettlements = punchInSettlementService.listByCondition(query);
|
|
|
|
|
+ return punchInSettlements.stream().map(settlement -> {
|
|
|
|
|
+ SettleDto dto = new SettleDto();
|
|
|
|
|
+ BeanUtils.copyProperties(settlement, dto);
|
|
|
|
|
+ return dto;
|
|
|
|
|
+ }).toList();
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|