package com.ruoyi.inspectiontask.service.impl; import com.ruoyi.inspectiontask.mapper.InspectionTaskMapper; import com.ruoyi.inspectiontask.pojo.InspectionTask; import com.ruoyi.inspectiontask.pojo.TimingTask; 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.DayOfWeek; import java.time.LocalDateTime; import java.time.LocalTime; import java.time.YearMonth; import java.time.LocalDate; import java.util.HashSet; import java.util.List; import java.util.Set; /** * 设备巡检定时任务测试类 * * 查询数据库中的巡检任务,根据登记日期、频次、开始日期与时间来生成巡检记录 * 并更新 timing_task 表的最后执行时间和下次执行时间 */ @SpringBootTest public class TimingTaskJobTest { @Autowired private InspectionTaskMapper inspectionTaskMapper; @Autowired private JdbcTemplate jdbcTemplate; /** * 测试:根据所有巡检任务生成巡检记录 * 从登记日期到今天,按频次每周生成一条记录 */ @Test void testGenerateInspectionRecordForAllTasks() { // 查询所有启用的巡检任务 String sql = "SELECT * FROM timing_task WHERE is_enabled = 1 AND deleted = 0"; List tasks = jdbcTemplate.query(sql, (rs, rowNum) -> { TimingTask task = new TimingTask(); task.setId(rs.getLong("id")); task.setTaskName(rs.getString("task_name")); task.setInspectionProject(rs.getString("inspection_project")); task.setTaskId(rs.getInt("task_id")); task.setInspectorIds(rs.getString("inspector_ids")); task.setInspectionLocation(rs.getString("inspection_location")); task.setFrequencyType(rs.getString("frequency_type")); task.setFrequencyDetail(rs.getString("frequency_detail")); task.setRemarks(rs.getString("remarks")); task.setRegistrantId(rs.getLong("registrant_id")); task.setRegistrant(rs.getString("registrant")); task.setTenantId(rs.getLong("tenant_id")); // 获取登记日期 java.sql.Date regDate = rs.getDate("registration_date"); if (regDate != null) { task.setRegistrationDate(regDate.toLocalDate()); } return task; }); System.out.println("=== 共找到 " + tasks.size() + " 个巡检任务 ===\n"); int totalRecords = 0; for (TimingTask task : tasks) { try { // 生成所有符合频次的记录 int recordCount = generateRecordsForTask(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 generateRecordsForTask(TimingTask task) { LocalDate startDate = task.getRegistrationDate(); if (startDate == null) { startDate = LocalDate.now(); } LocalDate endDate = LocalDate.now(); // 根据频次获取所有需要执行的日期 List executionDates = getExecutionDates(task.getFrequencyType(), task.getFrequencyDetail(), startDate, endDate); int count = 0; for (LocalDateTime executionDate : executionDates) { try { // 生成巡检记录 InspectionTask record = createInspectionRecord(task, executionDate); inspectionTaskMapper.insert(record); // 更新任务的上次执行时间 updateTaskLastExecutionTime(task.getId(), executionDate); count++; } catch (Exception e) { System.out.println(" ✗ 日期: " + executionDate + " | 失败: " + e.getMessage()); } } // 更新任务的下次执行时间 if (count > 0) { LocalDateTime lastExecution = executionDates.get(executionDates.size() - 1); LocalDateTime nextExecution = calculateNextExecutionTime(task.getFrequencyType(), task.getFrequencyDetail(), lastExecution); updateTaskNextExecutionTime(task.getId(), nextExecution); } return count; } /** * 获取指定日期范围内所有符合频次的执行时间 */ private List getExecutionDates(String frequencyType, String frequencyDetail, LocalDate startDate, LocalDate endDate) { List dates = new java.util.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 getDailyDates(LocalDate startDate, LocalDate endDate, String timeStr) { List dates = new java.util.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 getWeeklyDates(LocalDate startDate, LocalDate endDate, String detail) { List dates = new java.util.ArrayList<>(); String[] parts = detail.split(","); String dayOfWeekStr = parts[0]; LocalTime time = LocalTime.parse(parts[1]); Set targetDays = parseDayOfWeeks(dayOfWeekStr); LocalDate current = startDate; while (!current.isAfter(endDate)) { if (targetDays.contains(current.getDayOfWeek())) { dates.add(LocalDateTime.of(current, time)); } current = current.plusDays(1); } return dates; } private List getMonthlyDates(LocalDate startDate, LocalDate endDate, String detail) { List dates = new java.util.ArrayList<>(); String[] parts = detail.split(","); int dayOfMonth = Integer.parseInt(parts[0]); LocalTime time = LocalTime.parse(parts[1]); LocalDate current = startDate.plusMonths(0).withDayOfMonth(Math.min(dayOfMonth, startDate.lengthOfMonth())); while (!current.isAfter(endDate)) { dates.add(LocalDateTime.of(current, time)); current = current.plusMonths(1).withDayOfMonth(Math.min(dayOfMonth, current.plusMonths(1).lengthOfMonth())); } return dates; } private List getQuarterlyDates(LocalDate startDate, LocalDate endDate, String detail) { List dates = new java.util.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; } LocalDate current = startDate.withYear(startDate.getYear() + yearAdjust) .withMonth(targetMonth) .withDayOfMonth(Math.min(dayOfMonth, YearMonth.of(startDate.getYear() + yearAdjust, targetMonth).lengthOfMonth())); while (!current.isAfter(endDate)) { dates.add(LocalDateTime.of(current, time)); current = current.plusMonths(3).withDayOfMonth(Math.min(dayOfMonth, current.plusMonths(3).lengthOfMonth())); } return dates; } private Set parseDayOfWeeks(String dayOfWeekStr) { Set days = new HashSet<>(); String[] dayStrs = dayOfWeekStr.split("\\|"); for (String dayStr : dayStrs) { switch (dayStr.toUpperCase()) { case "MON": days.add(DayOfWeek.MONDAY); break; case "TUE": days.add(DayOfWeek.TUESDAY); break; case "WED": days.add(DayOfWeek.WEDNESDAY); break; case "THU": days.add(DayOfWeek.THURSDAY); break; case "FRI": days.add(DayOfWeek.FRIDAY); break; case "SAT": days.add(DayOfWeek.SATURDAY); break; case "SUN": days.add(DayOfWeek.SUNDAY); break; } } return days; } /** * 计算下次执行时间 */ 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) { String[] parts = detail.split(","); String dayOfWeekStr = parts[0]; LocalTime time = LocalTime.parse(parts[1]); Set targetDays = parseDayOfWeeks(dayOfWeekStr); LocalDateTime nextTime = current; while (true) { nextTime = nextTime.plusDays(1); if (targetDays.contains(nextTime.getDayOfWeek())) { return LocalDateTime.of(nextTime.toLocalDate(), time); } if (nextTime.isAfter(current.plusYears(1))) { throw new RuntimeException("无法找到下次执行时间"); } } } 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()); } /** * 创建巡检记录 */ private InspectionTask createInspectionRecord(TimingTask timingTask, LocalDateTime executionDate) { InspectionTask inspectionTask = new InspectionTask(); inspectionTask.setTaskName(timingTask.getTaskName()); inspectionTask.setInspectionProject(timingTask.getInspectionProject()); inspectionTask.setTaskId(timingTask.getTaskId()); inspectionTask.setInspectorId(timingTask.getInspectorIds()); inspectionTask.setInspectionLocation(timingTask.getInspectionLocation()); inspectionTask.setRemarks("自动生成自定时任务ID: " + timingTask.getId() + ";" + timingTask.getRemarks()); inspectionTask.setRegistrantId(timingTask.getRegistrantId()); inspectionTask.setFrequencyType(timingTask.getFrequencyType()); inspectionTask.setFrequencyDetail(timingTask.getFrequencyDetail()); inspectionTask.setTenantId(timingTask.getTenantId()); // 设置登记日期为执行日期 inspectionTask.setCreateTime(executionDate); inspectionTask.setUpdateTime(executionDate); return inspectionTask; } /** * 更新任务的上次执行时间 */ private void updateTaskLastExecutionTime(Long taskId, LocalDateTime lastExecutionTime) { String updateSql = "UPDATE timing_task SET last_execution_time = ? WHERE id = ?"; jdbcTemplate.update(updateSql, lastExecutionTime, taskId); } /** * 更新任务的下次执行时间 */ private void updateTaskNextExecutionTime(Long taskId, LocalDateTime nextExecutionTime) { String updateSql = "UPDATE timing_task SET next_execution_time = ? WHERE id = ?"; jdbcTemplate.update(updateSql, nextExecutionTime, taskId); } }