package com.xiaopeng.maintenance.schedule;
|
|
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
import com.xiaopeng.api.feignClient.account.XpOperationUserClient;
|
import com.xiaopeng.api.feignClient.vehicleConvoy.XpFleetOperationsClient;
|
import com.xiaopeng.api.feignClient.vehicleConvoy.XpFleetVehicleClient;
|
import com.xiaopeng.api.feignClient.vehicleConvoy.XpVehicleClient;
|
import com.xiaopeng.api.model.maintenance.XpClockIn;
|
import com.xiaopeng.api.model.maintenance.XpSchedulingDetail;
|
import com.xiaopeng.api.model.maintenance.XpShift;
|
import com.xiaopeng.api.model.vehicleConvoy.XpFleetOperations;
|
import com.xiaopeng.common.core.utils.DateUtils;
|
import com.xiaopeng.maintenance.mapper.XpClockInMapper;
|
import com.xiaopeng.maintenance.mapper.XpTaskMapper;
|
import com.xiaopeng.maintenance.mapper.XpTaskRuleMapper;
|
import com.xiaopeng.maintenance.mapper.XpTaskRuleRoleMapper;
|
import com.xiaopeng.maintenance.service.IXpClockInService;
|
import com.xiaopeng.maintenance.service.IXpSchedulingDetailService;
|
import com.xiaopeng.maintenance.service.IXpShiftService;
|
import org.slf4j.Logger;
|
import org.slf4j.LoggerFactory;
|
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.scheduling.annotation.Scheduled;
|
import org.springframework.stereotype.Component;
|
import org.springframework.util.CollectionUtils;
|
|
import java.time.LocalDate;
|
import java.time.LocalDateTime;
|
import java.util.ArrayList;
|
import java.util.List;
|
import java.util.stream.Collectors;
|
|
/**
|
* 打卡定时任务
|
* <p>
|
* 判断是否迟到或者缺卡
|
* </p>
|
*
|
* @author xiaochen
|
* @since 2026-02-27
|
*/
|
@Component
|
public class ClockInScheduleTask {
|
|
private static final Logger log = LoggerFactory.getLogger(ClockInScheduleTask.class);
|
|
@Autowired
|
private IXpClockInService xpClockInService;
|
@Autowired
|
private IXpSchedulingDetailService xpSchedulingDetailService;
|
@Autowired
|
private XpFleetOperationsClient xpFleetOperationsClient;
|
@Autowired
|
private IXpShiftService xpShiftService;
|
|
/**
|
* 每5分钟执行一次
|
*/
|
@Scheduled(fixedRate = 60*1000)
|
public void clockInScheduleTask() {
|
log.info("========== 开始执行打卡检查 ==========");
|
try {
|
// 查询下班卡在今天的
|
List<XpSchedulingDetail> clockOutPlanList = xpSchedulingDetailService.list(Wrappers.lambdaQuery(XpSchedulingDetail.class)
|
.likeRight(XpSchedulingDetail::getPlanTime, LocalDate.now()));
|
|
// 下班卡在昨天的
|
List<XpSchedulingDetail> clockOutPlanListLast = xpSchedulingDetailService.list(Wrappers.lambdaQuery(XpSchedulingDetail.class)
|
.likeRight(XpSchedulingDetail::getPlanTime, LocalDate.now().minusDays(1)));
|
|
if(!CollectionUtils.isEmpty(clockOutPlanList)){
|
List<Long> fleetIds = clockOutPlanList.stream().map(XpSchedulingDetail::getFleetId).distinct().collect(Collectors.toList());
|
// 查询所有车队的绑定人员
|
List<XpFleetOperations> xpFleetOperations = xpFleetOperationsClient.getOperationsIdsByFleetIds(fleetIds).getData();
|
// 查询班次
|
List<Long> shiftIds = clockOutPlanList.stream().map(XpSchedulingDetail::getShiftId).collect(Collectors.toList());
|
List<XpShift> xpShifts = xpShiftService.list(Wrappers.lambdaQuery(XpShift.class)
|
.in(XpShift::getId, shiftIds));
|
log.info("========== 查询到{}个车队 ==========", xpFleetOperations.size());
|
if(!CollectionUtils.isEmpty(xpShifts) && !CollectionUtils.isEmpty(xpFleetOperations)){
|
// 处理上班卡缺卡情况
|
// 过滤当前时间在班次下班打卡时间之后的数据 今日已过下班的班次
|
List<XpShift> shiftList = xpShifts.stream().filter(xpShift ->
|
DateUtils.stringToLocalDateTime(LocalDate.now() + " " + xpShift.getEndTime() + ":00").isBefore(LocalDateTime.now())).collect(Collectors.toList());
|
List<Long> ids = shiftList.stream().map(XpShift::getId).collect(Collectors.toList());
|
if(!CollectionUtils.isEmpty(ids)){
|
log.info("========== 进入上班过期的班次 ==========");
|
// 获取过期当前班次的排班明细 覆盖
|
List<XpSchedulingDetail> clockOutPlans = clockOutPlanList.stream().filter(xpSchedulingDetail -> ids.contains(xpSchedulingDetail.getShiftId())).collect(Collectors.toList());
|
List<Long> fleetIdIn = clockOutPlans.stream().map(XpSchedulingDetail::getFleetId).collect(Collectors.toList());
|
List<Long> operationsUserIds = xpFleetOperations.stream().filter(x -> fleetIdIn.contains(x.getFleetId()))
|
.map(XpFleetOperations::getOperationsUserId).distinct().collect(Collectors.toList());
|
// 批量查询人员打卡信息
|
List<XpClockIn> clockInList = xpClockInService.list(Wrappers.lambdaQuery(XpClockIn.class)
|
.in(XpClockIn::getAppUserId, operationsUserIds));
|
// 判断有哪些人员没有打卡信息
|
List<Long> noClockInUserIds = operationsUserIds.stream().filter(id -> clockInList.stream().noneMatch(clockIn -> clockIn.getAppUserId().equals(id))).collect(Collectors.toList());
|
if(!CollectionUtils.isEmpty(noClockInUserIds)){
|
log.info("========== 获取到{}个人员没有打卡信息 ==========", noClockInUserIds.size());
|
// 添加上班缺卡信息
|
List<XpClockIn> noClockInList = new ArrayList<>();
|
for (Long noClockInUserId : noClockInUserIds) {
|
// 通过用户id找到车队id
|
List<XpFleetOperations> operations = xpFleetOperations.stream().filter(x -> x.getOperationsUserId().equals(noClockInUserId)).collect(Collectors.toList());
|
if(!CollectionUtils.isEmpty(operations)){
|
Long fleetId = operations.get(0).getFleetId();
|
// 通过车队id和已过期的班次获取排班明细
|
List<XpSchedulingDetail> clockOutPlanExpiredList = clockOutPlanList.stream()
|
.filter(xpSchedulingDetail -> xpSchedulingDetail.getFleetId().equals(fleetId)
|
&& ids.contains(xpSchedulingDetail.getShiftId())).collect(Collectors.toList());
|
if(!CollectionUtils.isEmpty(clockOutPlanExpiredList)){
|
Long shiftId = clockOutPlanExpiredList.get(0).getShiftId();
|
XpClockIn xpClockIn = new XpClockIn();
|
xpClockIn.setAppUserId(noClockInUserId);
|
xpClockIn.setClockInTime(LocalDateTime.now());
|
xpClockIn.setClockInResult(3);
|
xpClockIn.setShiftId(shiftId);
|
noClockInList.add(xpClockIn);
|
}
|
}
|
}
|
if (!CollectionUtils.isEmpty(noClockInList)){
|
log.info("添加上班缺卡信息:{}", noClockInList);
|
xpClockInService.saveBatch(noClockInList);
|
}
|
}
|
}
|
|
// 处理下班卡缺卡情况
|
// 过滤当前时间在班次下班打卡时间之后5小时的数据 今日已过下班打卡时间5小时后的班次
|
List<XpShift> shiftListFive = xpShifts.stream().filter(xpShift ->
|
DateUtils.stringToLocalDateTime(LocalDate.now() + " " + xpShift.getEndTime() + ":00").plusMinutes(1).isBefore(LocalDateTime.now())).collect(Collectors.toList());
|
// DateUtils.stringToLocalDateTime(LocalDate.now() + " " + xpShift.getEndTime() + ":00").plusHours(5).isBefore(LocalDateTime.now())).collect(Collectors.toList());
|
List<Long> fiveIds = shiftListFive.stream().map(XpShift::getId).collect(Collectors.toList());
|
if(!CollectionUtils.isEmpty(fiveIds)){
|
log.info("========== 进入下班过期的班次 ==========");
|
List<XpSchedulingDetail> clockOutPlans = clockOutPlanList.stream().filter(xpSchedulingDetail -> fiveIds.contains(xpSchedulingDetail.getShiftId())).collect(Collectors.toList());
|
List<Long> fleetIdOut = clockOutPlans.stream().map(XpSchedulingDetail::getFleetId).collect(Collectors.toList());
|
// 查询所有车队的绑定人员
|
List<XpFleetOperations> xpFleetOperationsList = xpFleetOperationsClient.getOperationsIdsByFleetIds(fleetIdOut).getData();
|
// 获取过期当前班次的排班明细 覆盖
|
List<XpSchedulingDetail> fiveClockOutPlans = clockOutPlanList.stream().filter(xpSchedulingDetail -> fiveIds.contains(xpSchedulingDetail.getShiftId())).collect(Collectors.toList());
|
List<Long> fiveFleetIdIn = fiveClockOutPlans.stream().map(XpSchedulingDetail::getFleetId).collect(Collectors.toList());
|
// 查询所有车队的绑定人员
|
if(!CollectionUtils.isEmpty(xpFleetOperationsList)){
|
List<Long> operationsUserIdsFive = xpFleetOperationsList.stream().filter(x -> fiveFleetIdIn.contains(x.getFleetId()))
|
.map(XpFleetOperations::getOperationsUserId).distinct().collect(Collectors.toList());
|
// 批量查询人员打卡信息
|
List<XpClockIn> clockInListFive = xpClockInService.list(Wrappers.lambdaQuery(XpClockIn.class)
|
.in(XpClockIn::getAppUserId, operationsUserIdsFive)
|
.isNull(XpClockIn::getClockOutTime));
|
log.info("========== 获取到{}个人员没有下班打卡信息 ==========", clockInListFive.size());
|
if(!CollectionUtils.isEmpty(clockInListFive)){
|
for (XpClockIn xpClockIn : clockInListFive) {
|
xpClockIn.setClockOutTime(LocalDateTime.now());
|
xpClockIn.setClockOutResult(3);
|
xpClockIn.setAppUserId(null);
|
}
|
xpClockInService.updateBatchById(clockInListFive);
|
log.info("========== 修改为下班缺卡 ==========");
|
}
|
}
|
}
|
}
|
}
|
|
if (!CollectionUtils.isEmpty(clockOutPlanListLast)){
|
List<Long> fleetIds = clockOutPlanListLast.stream().map(XpSchedulingDetail::getFleetId).distinct().collect(Collectors.toList());
|
// 查询所有车队的绑定人员
|
List<XpFleetOperations> xpFleetOperations = xpFleetOperationsClient.getOperationsIdsByFleetIds(fleetIds).getData();
|
// 查询班次
|
List<Long> shiftIds = clockOutPlanListLast.stream().map(XpSchedulingDetail::getShiftId).collect(Collectors.toList());
|
List<XpShift> xpShifts = xpShiftService.list(Wrappers.lambdaQuery(XpShift.class)
|
.in(XpShift::getId, shiftIds));
|
log.info("========== 查询到{}个车队 ==========", xpFleetOperations.size());
|
|
// 处理下班卡缺卡情况
|
// 过滤当前时间在班次下班打卡时间之后5小时的数据 今日已过下班打卡时间5小时后的班次
|
List<XpShift> shiftListFive = xpShifts.stream().filter(xpShift ->
|
DateUtils.stringToLocalDateTime(LocalDate.now().minusDays(1) + " " + xpShift.getEndTime() + ":00").plusMinutes(1).isBefore(LocalDateTime.now())).collect(Collectors.toList());
|
// DateUtils.stringToLocalDateTime(LocalDate.now().minusDays(1) + " " + xpShift.getEndTime() + ":00").plusHours(5).isBefore(LocalDateTime.now())).collect(Collectors.toList());
|
List<Long> fiveIds = shiftListFive.stream().map(XpShift::getId).collect(Collectors.toList());
|
if(!CollectionUtils.isEmpty(fiveIds)){
|
log.info("========== 进入下班过期的班次 ==========");
|
// 获取过期当前班次的排班明细 覆盖
|
List<XpSchedulingDetail> fiveClockOutPlans = clockOutPlanListLast.stream().filter(xpSchedulingDetail -> fiveIds.contains(xpSchedulingDetail.getShiftId())).collect(Collectors.toList());
|
List<Long> fiveFleetIdIn = fiveClockOutPlans.stream().map(XpSchedulingDetail::getFleetId).collect(Collectors.toList());
|
// 查询所有车队的绑定人员
|
if(!CollectionUtils.isEmpty(xpFleetOperations)){
|
List<Long> operationsUserIdsFive = xpFleetOperations.stream().filter(x -> fiveFleetIdIn.contains(x.getFleetId()))
|
.map(XpFleetOperations::getOperationsUserId).distinct().collect(Collectors.toList());
|
// 批量查询人员打卡信息
|
List<XpClockIn> clockInListFive = xpClockInService.list(Wrappers.lambdaQuery(XpClockIn.class)
|
.in(XpClockIn::getAppUserId, operationsUserIdsFive)
|
.likeRight(XpClockIn::getClockInTime,LocalDate.now().minusDays(1))
|
.isNull(XpClockIn::getClockOutTime));
|
log.info("========== 获取到{}个人员没有下班打卡信息 ==========", clockInListFive.size());
|
if(!CollectionUtils.isEmpty(clockInListFive)){
|
for (XpClockIn xpClockIn : clockInListFive) {
|
xpClockIn.setAppUserId(null);
|
xpClockIn.setClockOutTime(LocalDateTime.now());
|
xpClockIn.setClockOutResult(3);
|
}
|
xpClockInService.updateBatchById(clockInListFive);
|
log.info("========== 修改为下班缺卡 ==========");
|
}
|
}
|
}
|
}
|
|
} catch (Exception e) {
|
log.error("执行打卡检查任务执行失败", e);
|
}
|
}
|
}
|