feat(schedule): 新增PDI检测任务超期及提醒逻辑

- 新增PdiTaskOverdueNotifyProcessor定时任务,每分钟检查未完成的PDI任务超期情况
- 根据任务完成时间和要求完成时间判断超期或即将超期,推送消息提醒质检人、帮办人及部门领导
- 添加QmsPdiTaskRecord实体字段pushRecords,记录超期提醒推送状态
- 修正任务完成时overdue字段设置逻辑,支持已有值保持不变
- 补充推送消息逻辑,避免重复推送超期或即将超期提醒
- 增强日志记录,方便监控定时任务执行情况
This commit is contained in:
funny 2026-05-08 15:18:03 +08:00
parent 858726758d
commit 6c6f881812
3 changed files with 265 additions and 3 deletions

View File

@ -229,12 +229,18 @@ public class QmsPdiInspectionResultsControllerService {
// 6. 根据整体判定+检测项结果设置状态有不合格则=3待流转全合格则=2已完成
boolean hasDefect = !overallResult || !failedItems.isEmpty();
boolean overdue = taskRecord.getRequiredCompletionTime() != null
&& now.isAfter(taskRecord.getRequiredCompletionTime());
// 校验 overdue 字段无值时根据完成时间与要求完成时间比较设置有值则保持原值
Boolean overdueValue = taskRecord.getOverdue();
if (overdueValue == null) {
overdueValue = taskRecord.getRequiredCompletionTime() != null
&& now.isAfter(taskRecord.getRequiredCompletionTime());
}
taskRecordService.lambdaUpdate()
.eq(QmsPdiTaskRecord::getId, taskRecord.getId())
.set(QmsPdiTaskRecord::getDetectionCompletionTime, now)
.set(QmsPdiTaskRecord::getOverdue, overdue)
.set(QmsPdiTaskRecord::getOverdue, overdueValue)
.set(QmsPdiTaskRecord::getInspectionEnable, hasDefect ? 3 : 2)
.update();

View File

@ -77,6 +77,11 @@ public class QmsPdiTaskRecord implements Serializable {
*/
private Boolean overdue;
/**
* 信息推送记录0=未推送1=已推送即将超时信息2=已推送超时信息
*/
private Short pushRecords;
/**
* 工厂编号
*/

View File

@ -0,0 +1,251 @@
package com.nflg.wms.scheduled.processor;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.nflg.wms.repository.entity.Department;
import com.nflg.wms.repository.entity.DictionaryItem;
import com.nflg.wms.repository.entity.QmsPdiDetectionRules;
import com.nflg.wms.repository.entity.QmsPdiTaskRecord;
import com.nflg.wms.repository.entity.QmsTodoItem;
import com.nflg.wms.repository.entity.UserInterior;
import com.nflg.wms.repository.service.IDepartmentService;
import com.nflg.wms.repository.service.IDictionaryItemService;
import com.nflg.wms.repository.service.IQmsPdiDetectionRulesService;
import com.nflg.wms.repository.service.IQmsPdiTaskRecordService;
import com.nflg.wms.repository.service.IQmsTodoItemService;
import com.nflg.wms.repository.service.IUserInteriorService;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Component;
import tech.powerjob.worker.core.processor.ProcessResult;
import tech.powerjob.worker.core.processor.TaskContext;
import tech.powerjob.worker.core.processor.sdk.BasicProcessor;
import tech.powerjob.worker.log.OmsLogger;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;
/**
* PDI检测任务超期通知定时任务
* 每分钟执行一次检测未完成的任务是否超期或即将超期并推送消息
*/
@Component(value = "PdiTaskOverdueNotifyProcessor")
public class PdiTaskOverdueNotifyProcessor implements BasicProcessor {
@Resource
private IQmsPdiTaskRecordService taskRecordService;
@Resource
private IQmsPdiDetectionRulesService detectionRulesService;
@Resource
private IUserInteriorService userInteriorService;
@Resource
private IDepartmentService departmentService;
@Resource
private IQmsTodoItemService todoItemService;
@Resource
private IDictionaryItemService dictionaryItemService;
@Override
public ProcessResult process(TaskContext context) {
OmsLogger omsLogger = context.getOmsLogger();
omsLogger.info("开始执行PDI检测任务超期通知定时任务");
try {
// 查询字典ID
DictionaryItem dictItem = dictionaryItemService.lambdaQuery()
.eq(DictionaryItem::getCode, "PDIDetectionTaskTimeoutReminder")
.one();
if (dictItem == null) {
omsLogger.error("未找到字典项PDIDetectionTaskTimeoutReminder");
return new ProcessResult(false, "未找到字典项");
}
Long sourceTypeId = dictItem.getId();
// 查询所有未完成检测的任务
List<QmsPdiTaskRecord> tasks = taskRecordService.lambdaQuery()
.isNull(QmsPdiTaskRecord::getDetectionCompletionTime)
.list();
omsLogger.info("共查询到【{}】条未完成任务", tasks.size());
LocalDateTime now = LocalDateTime.now();
int notifyCount = 0;
for (QmsPdiTaskRecord task : tasks) {
try {
if (task.getRequiredCompletionTime() == null) {
continue;
}
// 计算时间差分钟
long minutes = Duration.between(now, task.getRequiredCompletionTime()).toMinutes();
long hours = Math.abs(minutes) / 60;
if (minutes < 0) {
// 已超期
if (task.getPushRecords() == null || task.getPushRecords() != 2) {
// 更新超期状态和推送记录
taskRecordService.lambdaUpdate()
.eq(QmsPdiTaskRecord::getId, task.getId())
.set(QmsPdiTaskRecord::getOverdue, true)
.set(QmsPdiTaskRecord::getPushRecords, (short) 2)
.update();
// 查询质检人和帮办人
QmsPdiDetectionRules rules = detectionRulesService.getById(task.getDetectionRulesId());
if (rules == null || rules.getInspectorId() == null) {
omsLogger.warn("任务【{}】未找到质检人", task.getTaskNo());
continue;
}
Long inspectorId = rules.getInspectorId();
Long assistantId = task.getAssistantId();
// 查询质检人信息
UserInterior inspector = userInteriorService.lambdaQuery()
.eq(UserInterior::getUserId, inspectorId)
.one();
String inspectorName = inspector != null ? inspector.getUserName() : "未知";
String assistantName = "";
if (assistantId != null) {
UserInterior assistant = userInteriorService.lambdaQuery()
.eq(UserInterior::getUserId, assistantId)
.one();
assistantName = assistant != null ? assistant.getUserName() : "未知";
}
String assistantText = StrUtil.isNotBlank(assistantName) ? "+" + assistantName : "";
// 查询部门领导
Set<Long> leaderIds = new HashSet<>();
// 质检人的部门领导
if (inspector != null && inspector.getDeptId() != null) {
Department dept = departmentService.getById(inspector.getDeptId());
if (dept != null && dept.getHeadUserId() != null) {
leaderIds.add(dept.getHeadUserId());
}
}
// 帮办人的部门领导
if (assistantId != null) {
UserInterior assistant = userInteriorService.lambdaQuery()
.eq(UserInterior::getUserId, assistantId)
.one();
if (assistant != null && assistant.getDeptId() != null) {
Department dept = departmentService.getById(assistant.getDeptId());
if (dept != null && dept.getHeadUserId() != null) {
leaderIds.add(dept.getHeadUserId());
}
}
}
// 给部门领导推送消息
String messageContent = String.format("PDI检测任务[%s]已超期,检测人为[%s%s]",
task.getTaskNo(), inspectorName, assistantText);
for (Long leaderId : leaderIds) {
UserInterior leader = userInteriorService.lambdaQuery()
.eq(UserInterior::getUserId, leaderId)
.one();
QmsTodoItem todo = new QmsTodoItem()
.setCode(task.getTaskNo())
.setSourceTypeId(sourceTypeId)
.setSourceId(task.getId())
.setIsRead(false)
.setCreateUserId(leaderId)
.setCreateUserName(leader != null ? leader.getUserName() : "未知")
.setCreateTime(now);
todoItemService.save(todo);
omsLogger.info("向部门领导【{}】推送超期消息:{}", leaderId, messageContent);
}
notifyCount++;
}
} else if (hours <= 24) {
// 即将超期24小时内
if (task.getPushRecords() == null || task.getPushRecords() == 0) {
// 更新推送记录
taskRecordService.lambdaUpdate()
.eq(QmsPdiTaskRecord::getId, task.getId())
.set(QmsPdiTaskRecord::getPushRecords, (short) 1)
.update();
// 查询质检人和帮办人
QmsPdiDetectionRules rules = detectionRulesService.getById(task.getDetectionRulesId());
if (rules == null || rules.getInspectorId() == null) {
omsLogger.warn("任务【{}】未找到质检人", task.getTaskNo());
continue;
}
Long inspectorId = rules.getInspectorId();
Long assistantId = task.getAssistantId();
// 给质检人推送消息
long remainingHours = hours + (minutes % 60 != 0 ? 1 : 0);
String messageContent = String.format("PDI检测任务[%s]将在%d小时内到期请尽快完成",
task.getTaskNo(), remainingHours);
UserInterior inspector = userInteriorService.lambdaQuery()
.eq(UserInterior::getUserId, inspectorId)
.one();
QmsTodoItem todoInspector = new QmsTodoItem()
.setCode(task.getTaskNo())
.setSourceTypeId(sourceTypeId)
.setSourceId(task.getId())
.setIsRead(false)
.setCreateUserId(inspectorId)
.setCreateUserName(inspector != null ? inspector.getUserName() : "未知")
.setCreateTime(now);
todoItemService.save(todoInspector);
omsLogger.info("向质检人【{}】推送即将超期消息:{}", inspectorId, messageContent);
// 给帮办人推送消息
if (assistantId != null) {
UserInterior assistant = userInteriorService.lambdaQuery()
.eq(UserInterior::getUserId, assistantId)
.one();
QmsTodoItem todoAssistant = new QmsTodoItem()
.setCode(task.getTaskNo())
.setSourceTypeId(sourceTypeId)
.setSourceId(task.getId())
.setIsRead(false)
.setCreateUserId(assistantId)
.setCreateUserName(assistant != null ? assistant.getUserName() : "未知")
.setCreateTime(now);
todoItemService.save(todoAssistant);
omsLogger.info("向帮办人【{}】推送即将超期消息:{}", assistantId, messageContent);
}
notifyCount++;
}
}
} catch (Exception e) {
omsLogger.error("处理任务【{}】异常", task.getTaskNo(), e);
}
}
omsLogger.info("执行完成,共推送【{}】条消息", notifyCount);
return new ProcessResult(true, "执行完成,推送" + notifyCount + "条消息");
} catch (Exception e) {
omsLogger.error("执行异常", e);
return new ProcessResult(false, "执行异常: " + e.getMessage());
} finally {
omsLogger.info("执行结束");
}
}
}