吴羡
10 小时以前 2f07589b54d56085af77b50d580890cd4130b444
cnas-device/src/main/java/com/ruoyi/device/service/impl/DeviceExaminePlanServiceImpl.java
@@ -45,7 +45,10 @@
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.YearMonth;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -346,4 +349,170 @@
        return deviceExaminePlanDto;
    }
    /**
     * 按年份查询设备核查计划(不存在则自动创建),并自动补全已到点的设备明细
     */
    @Override
    public DeviceExaminePlanDto getOrCreatePlanByYear(String planYear) {
        if (StringUtils.isBlank(planYear)) {
            planYear = String.valueOf(LocalDate.now().getYear());
        }
        DeviceExaminePlan plan = getOrCreatePlanEntity(planYear);
        ensureExamineDetails(plan);
        DeviceExaminePlanDto planDto = new DeviceExaminePlanDto();
        BeanUtils.copyProperties(plan, planDto);
        DateTimeFormatter dateFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
        planDto.setWriteTimeStr(plan.getWriteTime() == null ? null : plan.getWriteTime().format(dateFormatter));
        planDto.setRatifyTimeStr(plan.getRatifyTime() == null ? null : plan.getRatifyTime().format(dateFormatter));
        if (plan.getWriteUserId() != null) {
            User writeUser = userMapper.selectById(plan.getWriteUserId());
            if (writeUser != null) {
                planDto.setWriteName(writeUser.getName());
            }
        }
        if (plan.getRatifyUserId() != null) {
            User ratifyUser = userMapper.selectById(plan.getRatifyUserId());
            if (ratifyUser != null) {
                planDto.setRatifyName(ratifyUser.getName());
            }
        }
        return planDto;
    }
    /**
     * 设备档案变更后,把设备同步到对应年份的设备核查计划明细
     */
    @Override
    public void syncDeviceExamineDetail(Device device) {
        LocalDate remind = calcExamineRemindDate(device);
        if (remind == null || remind.isAfter(LocalDate.now())) {
            return;
        }
        DeviceExaminePlan plan = getOrCreatePlanEntity(String.valueOf(remind.getYear()));
        fillExamineDetailIfAbsent(plan, device);
    }
    /**
     * 复核通过后,把设备档案的最近/下次核查日期滚动到本轮
     */
    @Override
    public void updateDeviceExamineDate(Integer planDetailsId) {
        DeviceExaminePlanDetails detail = deviceExaminePlanDetailsMapper.selectById(planDetailsId);
        if (detail == null || detail.getDeviceId() == null) {
            return;
        }
        Device device = deviceMapper.selectById(detail.getDeviceId());
        if (device == null) {
            return;
        }
        LocalDate checkDate = parseCheckDate(detail.getCheckTime());
        if (checkDate.isAfter(LocalDate.now())) {
            checkDate = LocalDate.now();
        }
        LocalDateTime checkDateTime = checkDate.atStartOfDay();
        // 只允许向前滚动,避免重复复核旧记录时把日期改回去
        if (device.getLastExamineDate() != null && !checkDateTime.isAfter(device.getLastExamineDate())) {
            return;
        }
        device.setLastExamineDate(checkDateTime);
        if (StringUtils.isNotBlank(device.getExamineCycle())) {
            try {
                device.setNextExamineDate(checkDateTime.plusMonths(Long.parseLong(device.getExamineCycle().trim())));
            } catch (NumberFormatException ignored) {
            }
        }
        deviceMapper.updateById(device);
    }
    /**
     * 查询年份对应的计划,不存在则创建
     */
    private DeviceExaminePlan getOrCreatePlanEntity(String planYear) {
        DeviceExaminePlan plan = baseMapper.selectOne(Wrappers.<DeviceExaminePlan>lambdaQuery()
                .eq(DeviceExaminePlan::getPlanYear, planYear)
                .orderByDesc(DeviceExaminePlan::getPlanId)
                .last("limit 1"));
        if (plan == null) {
            plan = new DeviceExaminePlan();
            plan.setPlanName(planYear + "年度设备核查计划");
            plan.setPlanYear(planYear);
            plan.setWriteUserId(SecurityUtils.getUserId().intValue());
            plan.setWriteTime(LocalDateTime.now());
            baseMapper.insert(plan);
        }
        return plan;
    }
    /**
     * 扫描所有设备,把已到点(下次核查日期前1个月起,含已过期)的设备补进本年度计划
     */
    private void ensureExamineDetails(DeviceExaminePlan plan) {
        List<Device> devices = deviceMapper.selectList(null);
        for (Device device : devices) {
            fillExamineDetailIfAbsent(plan, device);
        }
    }
    /**
     * 设备提醒起点:下次核查日期前1个月(没填下次日期时用最近日期+核查周期兜底)
     */
    private LocalDate calcExamineRemindDate(Device device) {
        LocalDateTime base = device.getNextExamineDate();
        if (base == null && device.getLastExamineDate() != null && StringUtils.isNotBlank(device.getExamineCycle())) {
            try {
                base = device.getLastExamineDate().plusMonths(Long.parseLong(device.getExamineCycle().trim()));
            } catch (NumberFormatException ignored) {
            }
        }
        return base == null ? null : base.toLocalDate().minusMonths(1);
    }
    /**
     * 已到点且计划中尚无该设备本轮明细时自动补一条
     */
    private void fillExamineDetailIfAbsent(DeviceExaminePlan plan, Device device) {
        LocalDate remind = calcExamineRemindDate(device);
        if (remind == null || remind.isAfter(LocalDate.now())) {
            return;
        }
        if (plan.getPlanYear() != null && String.valueOf(remind.getYear()).compareTo(plan.getPlanYear()) > 0) {
            return;
        }
        String checkTime = remind.format(DateTimeFormatter.ofPattern("yyyy-MM"));
        Long exist = deviceExaminePlanDetailsMapper.selectCount(Wrappers.<DeviceExaminePlanDetails>lambdaQuery()
                .eq(DeviceExaminePlanDetails::getPlanId, plan.getPlanId())
                .eq(DeviceExaminePlanDetails::getDeviceId, device.getId())
                .likeRight(DeviceExaminePlanDetails::getCheckTime, checkTime));
        if (exist != null && exist > 0) {
            return;
        }
        DeviceExaminePlanDetails detail = new DeviceExaminePlanDetails();
        detail.setPlanId(plan.getPlanId());
        detail.setDeviceId(device.getId());
        String deviceName = device.getDeviceName() == null ? "" : device.getDeviceName();
        if (StringUtils.isNotBlank(device.getSpecificationModel())) {
            deviceName = deviceName + " " + device.getSpecificationModel();
        }
        detail.setDeviceName(deviceName);
        detail.setDeviceNumber(device.getManagementNumber());
        detail.setCheckTime(checkTime);
        deviceExaminePlanDetailsMapper.insert(detail);
    }
    /**
     * 计划明细的核查时间可能是 yyyy-MM 或 yyyy-MM-dd,统一取月份首日
     */
    private LocalDate parseCheckDate(String checkTime) {
        if (StringUtils.isNotBlank(checkTime)) {
            String normalized = checkTime.trim().replace('.', '-').replace('/', '-');
            if (normalized.length() >= 7) {
                try {
                    return YearMonth.parse(normalized.substring(0, 7)).atDay(1);
                } catch (Exception ignored) {
                }
            }
        }
        return LocalDate.now();
    }
}