puzhibing
2026-03-12 d2ddb03ee094d1d546fd92ce1b7876a7d3ae0657
xp-robotaxi-maintenance-boot/src/main/java/com/xiaopeng/maintenance/schedule/ClockInScheduleTask.java
@@ -2,15 +2,21 @@
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;
@@ -19,6 +25,8 @@
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;
@@ -40,7 +48,10 @@
    private IXpClockInService xpClockInService;
    @Autowired
    private IXpSchedulingDetailService xpSchedulingDetailService;
    @Autowired
    private XpFleetOperationsClient xpFleetOperationsClient;
    @Autowired
    private IXpShiftService xpShiftService;
    /**
     * 每5分钟执行一次
@@ -49,20 +60,100 @@
    public void clockInScheduleTask() {
        log.info("========== 开始执行打卡检查 ==========");
        try {
            // 查询上班卡在今天的
            List<XpSchedulingDetail> clockInPlanList = xpSchedulingDetailService.list(Wrappers.lambdaQuery(XpSchedulingDetail.class)
                    .likeRight(XpSchedulingDetail::getPlanTime, LocalDate.now()));
            if(!CollectionUtils.isEmpty(clockInPlanList)){
                List<Long> fleetIds = clockInPlanList.stream().map(XpSchedulingDetail::getFleetId).collect(Collectors.toList());
                // 查询所有车队
            }
            // 查询下班卡在今天的
            List<XpSchedulingDetail> clockOutPlanList = xpSchedulingDetailService.list(Wrappers.lambdaQuery(XpSchedulingDetail.class)
                    .likeRight(XpSchedulingDetail::getPlanTime, LocalDate.now()));
            if(!CollectionUtils.isEmpty(clockOutPlanList)){
                List<Long> fleetIds = clockOutPlanList.stream().map(XpSchedulingDetail::getFleetId).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)
                        .eq(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)
                                .eq(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.saveOrUpdateBatch(noClockInList);
                            }
                        }
                    }
                    // 处理下班卡缺卡情况
                    // 过滤当前时间在班次下班打卡时间之后5小时的数据   今日已过下班打卡时间5小时后的班次
                    List<XpShift> shiftListFive = xpShifts.stream().filter(xpShift ->
                            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> 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(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)
                                    .eq(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);
                                }
                                xpClockInService.updateBatchById(clockInListFive);
                                log.info("========== 修改为下班缺卡 ==========");
                            }
                        }
                    }
                }
            }
        } catch (Exception e) {
            log.error("执行打卡检查任务执行失败", e);
        }