|
|
|
|
@ -12,6 +12,7 @@ import com.aucma.dms.mapper.DmsPlanMaintMapper;
|
|
|
|
|
import com.aucma.dms.service.IDmsBillsMaintInstanceService;
|
|
|
|
|
import com.aucma.dms.service.IDmsPlanMaintService;
|
|
|
|
|
import com.aucma.quartz.util.CronUtils;
|
|
|
|
|
import org.quartz.CronExpression;
|
|
|
|
|
import org.slf4j.Logger;
|
|
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
|
@ -19,6 +20,7 @@ import org.springframework.scheduling.annotation.Scheduled;
|
|
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
|
|
|
|
|
|
|
import java.text.ParseException;
|
|
|
|
|
import java.util.ArrayList;
|
|
|
|
|
import java.util.Date;
|
|
|
|
|
import java.util.List;
|
|
|
|
|
@ -313,18 +315,19 @@ public class DmsPlanMaintServiceImpl implements IDmsPlanMaintService {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 定时任务:每天0点根据保养计划生成保养工单
|
|
|
|
|
* 定时任务:每天凌晨1点一次性生成当天整天的保养工单
|
|
|
|
|
* 使用Mapper替代JdbcTemplate,生成已完成状态工单,工单中所有设备默认保养完成
|
|
|
|
|
* 若有异常可在网页端维护工单明细中的设备状态
|
|
|
|
|
* cron表达式:秒 分 时 日 月 周
|
|
|
|
|
*/
|
|
|
|
|
@Scheduled(cron = "0 0 0 * * ?")
|
|
|
|
|
@Scheduled(cron = "0 0 1 * * ?")
|
|
|
|
|
public void generateDailyMaintWorkOrders() {
|
|
|
|
|
log.info("========== 开始执行保养工单生成任务 ==========");
|
|
|
|
|
int count = 0;
|
|
|
|
|
int skipCount = 0;
|
|
|
|
|
try {
|
|
|
|
|
// 通过Mapper查询今天需要执行的保养计划(maint_time <= 今天)
|
|
|
|
|
// 通过Mapper查询“今天整天内应生成”的保养计划。
|
|
|
|
|
// 这里依赖SQL使用“小于次日0点”的上界,避免把次日00:00计划提前捞出来。
|
|
|
|
|
List<DmsPlanMaint> plans = dmsPlanMaintMapper.selectPendingMaintPlans();
|
|
|
|
|
|
|
|
|
|
for (DmsPlanMaint plan : plans) {
|
|
|
|
|
@ -343,7 +346,8 @@ public class DmsPlanMaintServiceImpl implements IDmsPlanMaintService {
|
|
|
|
|
if (insertRows > 0) {
|
|
|
|
|
count++;
|
|
|
|
|
log.info("已为保养计划[{}]生成已完成工单", planMaintCode);
|
|
|
|
|
// 更新计划的下次执行时间(根据cron表达式或默认+1天)
|
|
|
|
|
// 基于“当前计划时间”推进下次执行时间,
|
|
|
|
|
// 避免凌晨1点批量生成当天工单后,又把计划推进回当天稍晚时间,导致次日被重复捞取。
|
|
|
|
|
updateMaintPlanNextTime(plan);
|
|
|
|
|
} else {
|
|
|
|
|
skipCount++;
|
|
|
|
|
@ -372,7 +376,9 @@ public class DmsPlanMaintServiceImpl implements IDmsPlanMaintService {
|
|
|
|
|
Date nextTime = null;
|
|
|
|
|
String cronExpression = plan.getCronExpression();
|
|
|
|
|
if (cronExpression != null && !cronExpression.isEmpty()) {
|
|
|
|
|
nextTime = CronUtils.getNextExecution(cronExpression);
|
|
|
|
|
// 这里必须基于计划当前 maintTime 推进,而不能基于“当前系统时间”直接算下一次,
|
|
|
|
|
// 否则当天未来时点的计划会被错误推进到“今天稍后”,第二天凌晨仍会再次命中。
|
|
|
|
|
nextTime = calculateNextMaintTime(cronExpression, plan.getMaintTime());
|
|
|
|
|
}
|
|
|
|
|
if (nextTime == null) {
|
|
|
|
|
log.warn("保养计划下次执行时间计算为null, 使用默认+1天 | planMaintId={}, planMaintCode={}, cronExpression={}",
|
|
|
|
|
@ -387,4 +393,25 @@ public class DmsPlanMaintServiceImpl implements IDmsPlanMaintService {
|
|
|
|
|
e.getMessage(), e);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* 计算保养计划下次执行时间:
|
|
|
|
|
* 1) 基于计划当前 maintTime 推进;
|
|
|
|
|
* 2) 若算出的时间仍不晚于当前时间,则继续推进,直到晚于当前时间。
|
|
|
|
|
*/
|
|
|
|
|
private Date calculateNextMaintTime(String cronExpression, Date currentMaintTime) {
|
|
|
|
|
try {
|
|
|
|
|
CronExpression cron = new CronExpression(cronExpression);
|
|
|
|
|
Date now = new Date();
|
|
|
|
|
Date cursor = currentMaintTime != null ? currentMaintTime : now;
|
|
|
|
|
Date next = cron.getNextValidTimeAfter(cursor);
|
|
|
|
|
while (next != null && !next.after(now)) {
|
|
|
|
|
next = cron.getNextValidTimeAfter(next);
|
|
|
|
|
}
|
|
|
|
|
return next;
|
|
|
|
|
} catch (ParseException e) {
|
|
|
|
|
log.error("cron表达式非法,无法计算下次执行时间 | cronExpression={}, 异常信息: {}", cronExpression, e.getMessage(), e);
|
|
|
|
|
return null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|