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