| ¶Ô±ÈÐÂÎļþ |
| | |
| | | package com.ruoyi.device.service.impl; |
| | | |
| | | import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; |
| | | import com.ruoyi.device.mapper.MaintenanceTaskMapper; |
| | | import com.ruoyi.device.pojo.DeviceMaintenance; |
| | | import com.ruoyi.device.pojo.MaintenanceTask; |
| | | import org.junit.jupiter.api.Test; |
| | | import org.springframework.beans.factory.annotation.Autowired; |
| | | import org.springframework.boot.test.context.SpringBootTest; |
| | | import org.springframework.jdbc.core.JdbcTemplate; |
| | | |
| | | import java.time.LocalDateTime; |
| | | import java.time.LocalTime; |
| | | import java.time.YearMonth; |
| | | import java.time.LocalDate; |
| | | import java.time.DayOfWeek; |
| | | import java.util.ArrayList; |
| | | import java.util.List; |
| | | import java.util.Objects; |
| | | |
| | | /** |
| | | * 设å¤ä¿å
»ä»»å¡æµè¯ç±» |
| | | * |
| | | * æ¥è¯¢æ°æ®åºä¸çä¿å
»ä»»å¡ï¼æ ¹æ®ç»è®°æ¥æã颿¬¡ãå¼å§æ¥æä¸æ¶é´æ¥çæä¿å
»è®°å½ |
| | | * ä»ç»è®°æ¥æå°ä»å¤©ï¼æé¢æ¬¡çæææç¬¦åçè®°å½ |
| | | */ |
| | | @SpringBootTest |
| | | public class MaintenanceTaskJobTest { |
| | | |
| | | @Autowired |
| | | private MaintenanceTaskMapper maintenanceTaskMapper; |
| | | |
| | | @Autowired |
| | | private DeviceMaintenanceServiceImpl deviceMaintenanceService; |
| | | |
| | | @Autowired |
| | | private JdbcTemplate jdbcTemplate; |
| | | |
| | | /** |
| | | * æµè¯ï¼ææ¥æåæ£çæä¿å
»è®°å½ |
| | | * ä»ç»è®°æ¥æå°ä»å¤©ï¼ææ¥æé¡ºåºï¼æ¯å¤©çææè®¾å¤ä¿å
»è®°å½ä¸èµ·çæ |
| | | */ |
| | | @Test |
| | | void testGenerateOneByOne() { |
| | | // æ¥è¯¢ææå¯ç¨çä¿å
»ä»»å¡ |
| | | List<MaintenanceTask> tasks = maintenanceTaskMapper.selectList( |
| | | new LambdaQueryWrapper<MaintenanceTask>() |
| | | .eq(MaintenanceTask::getIsActive, 1) |
| | | .eq(MaintenanceTask::getDeleted, 0) |
| | | ); |
| | | |
| | | if (tasks.isEmpty()) { |
| | | System.out.println("=== æ²¡ææ¾å°ä¿å
»ä»»å¡ ==="); |
| | | return; |
| | | } |
| | | |
| | | // æ¾åºææ©åææçç»è®°æ¥æ |
| | | LocalDate earliestDate = tasks.stream() |
| | | .map(MaintenanceTask::getRegistrationDate) |
| | | .filter(Objects::nonNull) |
| | | .min(LocalDate::compareTo) |
| | | .orElse(LocalDate.now()); |
| | | LocalDate latestDate = LocalDate.now(); |
| | | |
| | | System.out.println("=== ç»è®°æ¥æèå´: " + earliestDate + " è³ " + latestDate + " ==="); |
| | | System.out.println("=== å
±æ¾å° " + tasks.size() + " 个ä¿å
»ä»»å¡ ===\n"); |
| | | |
| | | // ææ¥æé¡ºåºçæï¼æ¯å¤©çæä¸æ¬¡ |
| | | LocalDate currentDate = earliestDate; |
| | | int totalRecords = 0; |
| | | |
| | | while (!currentDate.isAfter(latestDate)) { |
| | | final LocalDate date = currentDate; |
| | | final List<DeviceMaintenance> recordsToSave = new ArrayList<>(); |
| | | |
| | | // æ¾åºå½å¤©éè¦ä¿å
»çææä»»å¡ |
| | | for (MaintenanceTask task : tasks) { |
| | | LocalDate startDate = task.getRegistrationDate() != null ? task.getRegistrationDate() : LocalDate.now(); |
| | | if (date.isBefore(startDate)) { |
| | | continue; // è·³è¿ç»è®°æ¥æä¹åçæ¥æ |
| | | } |
| | | |
| | | // æ£æ¥è¯¥ä»»å¡ç颿¬¡æ¯å¦å¹é
å½å¤© |
| | | if (isExecutionDate(task.getFrequencyType(), task.getFrequencyDetail(), startDate, date)) { |
| | | LocalTime time = getExecutionTime(task.getFrequencyDetail()); |
| | | LocalDateTime executionDateTime = LocalDateTime.of(date, time); |
| | | |
| | | DeviceMaintenance record = createMaintenanceRecord(task, executionDateTime); |
| | | recordsToSave.add(record); |
| | | } |
| | | } |
| | | |
| | | // 妿å½å¤©æè®°å½ï¼æ¹éä¿å |
| | | if (!recordsToSave.isEmpty()) { |
| | | for (DeviceMaintenance record : recordsToSave) { |
| | | try { |
| | | deviceMaintenanceService.save(record); |
| | | System.out.println(" â è®¡åæ¥æ: " + date + " | 设å¤: " + record.getDeviceName() |
| | | + " | è®°å½ID: " + record.getId()); |
| | | } catch (Exception e) { |
| | | System.out.println(" â è®¡åæ¥æ: " + date + " | 设å¤: " + record.getDeviceName() |
| | | + " | 失败: " + e.getMessage()); |
| | | } |
| | | } |
| | | totalRecords += recordsToSave.size(); |
| | | System.out.println(" === æ¥æ " + date + " å
±çæ " + recordsToSave.size() + " æ¡è®°å½ ===\n"); |
| | | } |
| | | |
| | | currentDate = currentDate.plusDays(1); |
| | | } |
| | | |
| | | System.out.println("=== æ§è¡å®æ: å
±çæ " + totalRecords + " æ¡è®°å½ ==="); |
| | | } |
| | | |
| | | /** |
| | | * æ£æ¥æå®æ¥ææ¯å¦ç¬¦åä»»å¡çæ§è¡é¢æ¬¡ |
| | | */ |
| | | private boolean isExecutionDate(String frequencyType, String frequencyDetail, LocalDate startDate, LocalDate checkDate) { |
| | | if (checkDate.isBefore(startDate)) { |
| | | return false; |
| | | } |
| | | |
| | | switch (frequencyType) { |
| | | case "DAILY": |
| | | return true; // æ¯å¤©é½éè¦æ§è¡ |
| | | case "WEEKLY": |
| | | return isWeeklyMatch(frequencyDetail, checkDate); |
| | | case "MONTHLY": |
| | | return isMonthlyMatch(frequencyDetail, checkDate); |
| | | case "QUARTERLY": |
| | | return isQuarterlyMatch(frequencyDetail, checkDate); |
| | | default: |
| | | return false; |
| | | } |
| | | } |
| | | |
| | | private boolean isWeeklyMatch(String detail, LocalDate date) { |
| | | String[] parts = detail.split(","); |
| | | String dayOfWeekStr = parts[0]; |
| | | DayOfWeek targetDay = parseDayOfWeek(dayOfWeekStr); |
| | | return date.getDayOfWeek() == targetDay; |
| | | } |
| | | |
| | | private boolean isMonthlyMatch(String detail, LocalDate date) { |
| | | String[] parts = detail.split(","); |
| | | int targetDay = Integer.parseInt(parts[0]); |
| | | return date.getDayOfMonth() == targetDay; |
| | | } |
| | | |
| | | private boolean isQuarterlyMatch(String detail, LocalDate date) { |
| | | String[] parts = detail.split(","); |
| | | int quarterMonth = Integer.parseInt(parts[0]); // å£åº¦ä¸ç第å 个æ |
| | | int targetDay = Integer.parseInt(parts[1]); |
| | | |
| | | int currentMonth = date.getMonthValue(); |
| | | int monthInQuarter = (currentMonth - 1) % 3 + 1; |
| | | |
| | | return monthInQuarter == quarterMonth && date.getDayOfMonth() == targetDay; |
| | | } |
| | | |
| | | private LocalTime getExecutionTime(String frequencyDetail) { |
| | | String[] parts = frequencyDetail.split(","); |
| | | if (parts.length >= 2 && (parts.length == 2 || parts.length == 3)) { |
| | | return LocalTime.parse(parts[parts.length - 1]); |
| | | } |
| | | return LocalTime.of(9, 0); // é»è®¤æ¶é´ |
| | | } |
| | | |
| | | /** |
| | | * æµè¯ï¼æ ¹æ®ææä¿å
»ä»»å¡çæè®¾å¤ä¿å
»è®°å½ |
| | | * æé¡ºåºå¤çæ¯ä¸ªä»»å¡ï¼ä»ç»è®°æ¥æå°ä»å¤©ï¼æé¢æ¬¡ä¾æ¬¡çæææç¬¦åçè®°å½ |
| | | */ |
| | | @Test |
| | | void testGenerateMaintenanceRecordForAllTasks() { |
| | | // æ¥è¯¢ææå¯ç¨çä¿å
»ä»»å¡ï¼æIDæåº |
| | | List<MaintenanceTask> tasks = maintenanceTaskMapper.selectList( |
| | | new LambdaQueryWrapper<MaintenanceTask>() |
| | | .eq(MaintenanceTask::getIsActive, 1) |
| | | .eq(MaintenanceTask::getDeleted, 0) |
| | | .orderByAsc(MaintenanceTask::getId) |
| | | ); |
| | | |
| | | System.out.println("=== å
±æ¾å° " + tasks.size() + " 个ä¿å
»ä»»å¡ ===\n"); |
| | | |
| | | int totalRecords = 0; |
| | | for (MaintenanceTask task : tasks) { |
| | | try { |
| | | // æé¡ºåºçæè¯¥ä»»å¡ææç¬¦å颿¬¡çè®°å½ |
| | | int recordCount = generateRecordsForTaskSequentially(task); |
| | | totalRecords += recordCount; |
| | | System.out.println("â ä»»å¡ID: " + task.getId() + " | " + task.getTaskName() |
| | | + " | ç»è®°æ¥æ: " + task.getRegistrationDate() |
| | | + " | çæè®°å½æ°: " + recordCount); |
| | | } catch (Exception e) { |
| | | System.out.println("â ä»»å¡ID: " + task.getId() + " | " + task.getTaskName() + " | 失败: " + e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | System.out.println("\n=== æ§è¡å®æ: å
±çæ " + totalRecords + " æ¡è®°å½ ==="); |
| | | } |
| | | |
| | | /** |
| | | * 为åä¸ªä»»å¡æé¡ºåºçæææç¬¦å颿¬¡çè®°å½ |
| | | */ |
| | | private int generateRecordsForTaskSequentially(MaintenanceTask task) { |
| | | LocalDate startDate = task.getRegistrationDate(); |
| | | if (startDate == null) { |
| | | startDate = LocalDate.now(); |
| | | } |
| | | LocalDate endDate = LocalDate.now(); |
| | | |
| | | // æ ¹æ®é¢æ¬¡è·åææéè¦æ§è¡çæ¥æ |
| | | List<LocalDateTime> executionDates = getExecutionDates(task.getFrequencyType(), task.getFrequencyDetail(), startDate, endDate); |
| | | |
| | | if (executionDates.isEmpty()) { |
| | | return 0; |
| | | } |
| | | |
| | | int count = 0; |
| | | for (LocalDateTime executionDate : executionDates) { |
| | | try { |
| | | // æé¡ºåºçæä¿å
»è®°å½ |
| | | DeviceMaintenance record = createMaintenanceRecord(task, executionDate); |
| | | deviceMaintenanceService.save(record); |
| | | count++; |
| | | } catch (Exception e) { |
| | | System.out.println(" â æ¥æ: " + executionDate + " | 失败: " + e.getMessage()); |
| | | } |
| | | } |
| | | |
| | | // æ´æ°ä»»å¡ç䏿¬¡æ§è¡æ¶é´ |
| | | if (count > 0) { |
| | | // first_execution = ç¬¬ä¸æ¡è®°å½çæ¥æ = last_execution_time |
| | | LocalDateTime firstExecution = executionDates.get(0); |
| | | // next_execution = æå䏿¡è®°å½çä¸ä¸æ¬¡æ§è¡æ¥æ |
| | | LocalDateTime lastExecution = executionDates.get(executionDates.size() - 1); |
| | | LocalDateTime nextExecution = calculateNextExecutionTime(task.getFrequencyType(), task.getFrequencyDetail(), lastExecution); |
| | | updateTaskExecutionTime(task.getId(), firstExecution, nextExecution); |
| | | } |
| | | |
| | | return count; |
| | | } |
| | | |
| | | /** |
| | | * è·åæå®æ¥æèå´å
ææç¬¦å颿¬¡çæ§è¡æ¶é´ |
| | | */ |
| | | private List<LocalDateTime> getExecutionDates(String frequencyType, String frequencyDetail, LocalDate startDate, LocalDate endDate) { |
| | | List<LocalDateTime> dates = new ArrayList<>(); |
| | | |
| | | switch (frequencyType) { |
| | | case "DAILY": |
| | | dates.addAll(getDailyDates(startDate, endDate, frequencyDetail)); |
| | | break; |
| | | case "WEEKLY": |
| | | dates.addAll(getWeeklyDates(startDate, endDate, frequencyDetail)); |
| | | break; |
| | | case "MONTHLY": |
| | | dates.addAll(getMonthlyDates(startDate, endDate, frequencyDetail)); |
| | | break; |
| | | case "QUARTERLY": |
| | | dates.addAll(getQuarterlyDates(startDate, endDate, frequencyDetail)); |
| | | break; |
| | | } |
| | | |
| | | return dates; |
| | | } |
| | | |
| | | private List<LocalDateTime> getDailyDates(LocalDate startDate, LocalDate endDate, String timeStr) { |
| | | List<LocalDateTime> dates = new ArrayList<>(); |
| | | LocalTime time = LocalTime.parse(timeStr); |
| | | |
| | | LocalDate current = startDate; |
| | | while (!current.isAfter(endDate)) { |
| | | dates.add(LocalDateTime.of(current, time)); |
| | | current = current.plusDays(1); |
| | | } |
| | | return dates; |
| | | } |
| | | |
| | | private List<LocalDateTime> getMonthlyDates(LocalDate startDate, LocalDate endDate, String detail) { |
| | | List<LocalDateTime> dates = new ArrayList<>(); |
| | | String[] parts = detail.split(","); |
| | | int dayOfMonth = Integer.parseInt(parts[0]); |
| | | LocalTime time = LocalTime.parse(parts[1]); |
| | | |
| | | // ä»ç»è®°æ¥ææå¨ææ¾ç¬¬ä¸ä¸ªç¬¦åæ¡ä»¶çæ¥æ |
| | | int actualDay = Math.min(dayOfMonth, startDate.lengthOfMonth()); |
| | | LocalDate current = startDate.withDayOfMonth(actualDay); |
| | | |
| | | // 妿è¿ä¸ªæ¥æå¨ç»è®°æ¥æä¹åï¼å¾åæ¨ä¸ä¸ªæ |
| | | if (current.isBefore(startDate)) { |
| | | current = current.plusMonths(1); |
| | | actualDay = Math.min(dayOfMonth, current.lengthOfMonth()); |
| | | current = current.withDayOfMonth(actualDay); |
| | | } |
| | | |
| | | while (!current.isAfter(endDate)) { |
| | | dates.add(LocalDateTime.of(current, time)); |
| | | current = current.plusMonths(1); |
| | | actualDay = Math.min(dayOfMonth, current.lengthOfMonth()); |
| | | current = current.withDayOfMonth(actualDay); |
| | | } |
| | | return dates; |
| | | } |
| | | |
| | | private List<LocalDateTime> getWeeklyDates(LocalDate startDate, LocalDate endDate, String detail) { |
| | | List<LocalDateTime> dates = new ArrayList<>(); |
| | | String[] parts = detail.split(","); |
| | | String dayOfWeekStr = parts[0]; |
| | | LocalTime time = LocalTime.parse(parts[1]); |
| | | |
| | | java.time.DayOfWeek targetDay = parseDayOfWeek(dayOfWeekStr); |
| | | |
| | | LocalDate current = startDate; |
| | | while (!current.isAfter(endDate)) { |
| | | if (current.getDayOfWeek() == targetDay) { |
| | | dates.add(LocalDateTime.of(current, time)); |
| | | } |
| | | current = current.plusDays(1); |
| | | } |
| | | return dates; |
| | | } |
| | | |
| | | private List<LocalDateTime> getQuarterlyDates(LocalDate startDate, LocalDate endDate, String detail) { |
| | | List<LocalDateTime> dates = new ArrayList<>(); |
| | | String[] parts = detail.split(","); |
| | | int quarterMonth = Integer.parseInt(parts[0]); |
| | | int dayOfMonth = Integer.parseInt(parts[1]); |
| | | LocalTime time = LocalTime.parse(parts[2]); |
| | | |
| | | int currentMonth = startDate.getMonthValue(); |
| | | int targetMonth = ((currentMonth - 1) / 3) * 3 + quarterMonth; |
| | | int yearAdjust = 0; |
| | | |
| | | if (targetMonth > 12) { |
| | | targetMonth -= 12; |
| | | yearAdjust = 1; |
| | | } |
| | | |
| | | int actualDay = Math.min(dayOfMonth, YearMonth.of(startDate.getYear() + yearAdjust, targetMonth).lengthOfMonth()); |
| | | LocalDate current = startDate.withYear(startDate.getYear() + yearAdjust) |
| | | .withMonth(targetMonth) |
| | | .withDayOfMonth(actualDay); |
| | | |
| | | while (!current.isAfter(endDate)) { |
| | | dates.add(LocalDateTime.of(current, time)); |
| | | current = current.plusMonths(3); |
| | | actualDay = Math.min(dayOfMonth, current.lengthOfMonth()); |
| | | current = current.withDayOfMonth(actualDay); |
| | | } |
| | | return dates; |
| | | } |
| | | |
| | | private java.time.DayOfWeek parseDayOfWeek(String dayOfWeekStr) { |
| | | switch (dayOfWeekStr.toUpperCase()) { |
| | | case "MON": return java.time.DayOfWeek.MONDAY; |
| | | case "TUE": return java.time.DayOfWeek.TUESDAY; |
| | | case "WED": return java.time.DayOfWeek.WEDNESDAY; |
| | | case "THU": return java.time.DayOfWeek.THURSDAY; |
| | | case "FRI": return java.time.DayOfWeek.FRIDAY; |
| | | case "SAT": return java.time.DayOfWeek.SATURDAY; |
| | | case "SUN": return java.time.DayOfWeek.SUNDAY; |
| | | default: throw new IllegalArgumentException("æ æçææå : " + dayOfWeekStr); |
| | | } |
| | | } |
| | | |
| | | /** |
| | | * å建ä¿å
»è®°å½ |
| | | */ |
| | | private DeviceMaintenance createMaintenanceRecord(MaintenanceTask task, LocalDateTime executionDate) { |
| | | DeviceMaintenance record = new DeviceMaintenance(); |
| | | record.setDeviceName(task.getTaskName()); |
| | | record.setMaintenanceTaskId(task.getId()); |
| | | record.setDeviceLedgerId(task.getTaskId()); |
| | | record.setMaintenancePlanTime(executionDate); |
| | | record.setMaintenanceActuallyName(task.getMaintenancePerson()); |
| | | record.setFrequencyType(task.getFrequencyType()); |
| | | record.setFrequencyDetail(task.getFrequencyDetail()); |
| | | record.setTenantId(task.getTenantId()); |
| | | record.setStatus(0); // å¾
ä¿å
» |
| | | record.setDeviceModel(task.getDeviceModel()); |
| | | record.setMachineryCategory(task.getMachineryCategory()); |
| | | record.setCreateUser(Integer.parseInt(task.getRegistrantId().toString())); |
| | | record.setUpdateTime(executionDate); |
| | | record.setCreateTime(executionDate); |
| | | record.setUpdateUser(Integer.parseInt(task.getRegistrantId().toString())); |
| | | return record; |
| | | } |
| | | |
| | | /** |
| | | * æ´æ°ä»»å¡çæ§è¡æ¶é´ |
| | | */ |
| | | private void updateTaskExecutionTime(Long taskId, LocalDateTime lastExecutionTime, LocalDateTime nextExecutionTime) { |
| | | String sql = "UPDATE maintenance_task SET last_execution_time = ?, next_execution_time = ? WHERE id = ?"; |
| | | jdbcTemplate.update(sql, lastExecutionTime, nextExecutionTime, taskId); |
| | | } |
| | | |
| | | /** |
| | | * 计ç®ä¸æ¬¡æ§è¡æ¶é´ |
| | | */ |
| | | private LocalDateTime calculateNextExecutionTime(String frequencyType, String frequencyDetail, LocalDateTime currentTime) { |
| | | return switch (frequencyType) { |
| | | case "DAILY" -> calculateDailyNextTime(frequencyDetail, currentTime); |
| | | case "WEEKLY" -> calculateWeeklyNextTime(frequencyDetail, currentTime); |
| | | case "MONTHLY" -> calculateMonthlyNextTime(frequencyDetail, currentTime); |
| | | case "QUARTERLY" -> calculateQuarterlyNextTime(frequencyDetail, currentTime); |
| | | default -> throw new IllegalArgumentException("䏿¯æç颿¬¡ç±»å: " + frequencyType); |
| | | }; |
| | | } |
| | | |
| | | private LocalDateTime calculateDailyNextTime(String timeStr, LocalDateTime current) { |
| | | LocalTime executionTime = LocalTime.parse(timeStr); |
| | | LocalDateTime nextTime = LocalDateTime.of(current.toLocalDate(), executionTime); |
| | | return current.isBefore(nextTime) ? nextTime : nextTime.plusDays(1); |
| | | } |
| | | |
| | | private LocalDateTime calculateMonthlyNextTime(String detail, LocalDateTime current) { |
| | | String[] parts = detail.split(","); |
| | | int dayOfMonth = Integer.parseInt(parts[0]); |
| | | LocalTime time = LocalTime.parse(parts[1]); |
| | | return current.plusMonths(1) |
| | | .withDayOfMonth(Math.min(dayOfMonth, current.plusMonths(1).toLocalDate().lengthOfMonth())) |
| | | .with(time); |
| | | } |
| | | |
| | | private LocalDateTime calculateWeeklyNextTime(String detail, LocalDateTime current) { |
| | | return current.plusWeeks(1); |
| | | } |
| | | |
| | | private LocalDateTime calculateQuarterlyNextTime(String detail, LocalDateTime current) { |
| | | String[] parts = detail.split(","); |
| | | int quarterMonth = Integer.parseInt(parts[0]); |
| | | int dayOfMonth = Integer.parseInt(parts[1]); |
| | | LocalTime time = LocalTime.parse(parts[2]); |
| | | |
| | | int currentMonthInQuarter = (current.getMonthValue() - 1) % 3 + 1; |
| | | |
| | | YearMonth targetYearMonth; |
| | | if (currentMonthInQuarter < quarterMonth) { |
| | | targetYearMonth = YearMonth.from(current).plusMonths(quarterMonth - currentMonthInQuarter); |
| | | } else { |
| | | targetYearMonth = YearMonth.from(current).plusMonths(3 - currentMonthInQuarter + quarterMonth); |
| | | } |
| | | |
| | | int adjustedDay = Math.min(dayOfMonth, targetYearMonth.lengthOfMonth()); |
| | | return LocalDateTime.of(targetYearMonth.getYear(), targetYearMonth.getMonthValue(), adjustedDay, time.getHour(), time.getMinute()); |
| | | } |
| | | } |