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<TimingTask> 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<LocalDateTime> 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<LocalDateTime> getExecutionDates(String frequencyType, String frequencyDetail, LocalDate startDate, LocalDate endDate) {
|
List<LocalDateTime> 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<LocalDateTime> getDailyDates(LocalDate startDate, LocalDate endDate, String timeStr) {
|
List<LocalDateTime> 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<LocalDateTime> getWeeklyDates(LocalDate startDate, LocalDate endDate, String detail) {
|
List<LocalDateTime> dates = new java.util.ArrayList<>();
|
String[] parts = detail.split(",");
|
String dayOfWeekStr = parts[0];
|
LocalTime time = LocalTime.parse(parts[1]);
|
|
Set<DayOfWeek> 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<LocalDateTime> getMonthlyDates(LocalDate startDate, LocalDate endDate, String detail) {
|
List<LocalDateTime> 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<LocalDateTime> getQuarterlyDates(LocalDate startDate, LocalDate endDate, String detail) {
|
List<LocalDateTime> 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<DayOfWeek> parseDayOfWeeks(String dayOfWeekStr) {
|
Set<DayOfWeek> 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<DayOfWeek> 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);
|
}
|
}
|