| | |
| | | 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; |
| | |
| | | |
| | | 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(); |
| | | } |
| | | } |