Commit 9d92e76e authored by 鲁鸿波's avatar 鲁鸿波

所有作业3天未完成的,需要重新发起申请。

危险作业到交底环节后按固定时间判断是否超时,超时自动取消
parent b60097f4
...@@ -453,6 +453,7 @@ COMMENT ON COLUMN t_hazard_work_plan.is_full IS '是否7~9人(1:是,2:否)'; ...@@ -453,6 +453,7 @@ COMMENT ON COLUMN t_hazard_work_plan.is_full IS '是否7~9人(1:是,2:否)';
INSERT INTO "t_sys_dict_type" ("dict_id", "dict_name", "dict_type", "is_sys", "status", "create_by", "create_date", "update_by", "update_date", "remarks", "parent_id", "parent_ids", "tree_sort", "cascaded") VALUES ('1', '危险作业超时检测是否可以执行', 'plan_expired', '1', '0', NULL, '2025-11-28 15:30:11', NULL, '2025-11-28 15:30:11', NULL, NULL, NULL, NULL, '0'); INSERT INTO "t_sys_dict_type" ("dict_id", "dict_name", "dict_type", "is_sys", "status", "create_by", "create_date", "update_by", "update_date", "remarks", "parent_id", "parent_ids", "tree_sort", "cascaded") VALUES ('1', '危险作业超时检测是否可以执行', 'plan_expired', '1', '0', NULL, '2025-11-28 15:30:11', NULL, '2025-11-28 15:30:11', NULL, NULL, NULL, NULL, '0');
INSERT INTO t_sys_dict_data" ("dict_data_id", "dict_id", "dict_key", "dict_value", "tree_sort", "status", "create_by", "create_date", "update_by", "update_date", "remarks", "parent_id", "parent_ids") VALUES ('4', '1', '1', '可以执行', '0', '0', NULL, '2025-11-28 15:31:44', NULL, '2025-11-28 15:31:44', NULL, '0', '0,'); INSERT INTO t_sys_dict_data" ("dict_data_id", "dict_id", "dict_key", "dict_value", "tree_sort", "status", "create_by", "create_date", "update_by", "update_date", "remarks", "parent_id", "parent_ids") VALUES ('4', '1', '1', '可以执行', '0', '0', NULL, '2025-11-28 15:31:44', NULL, '2025-11-28 15:31:44', NULL, '0', '0,');
INSERT INTO "public"."t_sys_dict_data" ("dict_data_id", "dict_id", "dict_key", "dict_value", "tree_sort", "status", "create_by", "create_date", "update_by", "update_date", "remarks", "parent_id", "parent_ids") VALUES ('5ba9557a160d4d2290128553c473028b', '60c11c98359b4cd09b7220202abf9e0b', '12', '已超时自动取消', '12', '0', '1242684364872761344', '2025-12-01 16:29:54', '1242684364872761344', '2025-12-01 16:29:54', '', '0', '0,');
添加表t_hazard_work_plan_expired_log 添加表t_hazard_work_plan_expired_log
......
...@@ -3,7 +3,6 @@ package com.testor.common.scheduler; ...@@ -3,7 +3,6 @@ package com.testor.common.scheduler;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils; import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.testor.biz.sys.dict.data.model.domain.SysDictData; import com.testor.biz.sys.dict.data.model.domain.SysDictData;
import com.testor.biz.sys.org.model.domain.SysOrg;
import com.testor.common.core.constant.Constants; import com.testor.common.core.constant.Constants;
import com.testor.module.hazard.dao.THazardWorkPlanDao; import com.testor.module.hazard.dao.THazardWorkPlanDao;
import com.testor.module.hazard.dao.THazardWorkPlanExpiredLogDao; import com.testor.module.hazard.dao.THazardWorkPlanExpiredLogDao;
...@@ -14,22 +13,32 @@ import com.testor.module.sys.model.domian.NewSysOrg; ...@@ -14,22 +13,32 @@ import com.testor.module.sys.model.domian.NewSysOrg;
import com.testor.module.sys.service.NewSysDictDataService; import com.testor.module.sys.service.NewSysDictDataService;
import com.testor.common.util.DangerousOperationValidator; import com.testor.common.util.DangerousOperationValidator;
import com.testor.module.sys.service.NewSysOrgService; import com.testor.module.sys.service.NewSysOrgService;
import com.tongtech.tfw.backend.common.biz.constants.BizConstants;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.HistoryService; import org.flowable.engine.HistoryService;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService; import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.runtime.ChangeActivityStateBuilder;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ProcessInstance; import org.flowable.engine.runtime.ProcessInstance;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled; import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.*; import java.util.*;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.UserTask;
import org.flowable.bpmn.model.FlowElement;
import org.flowable.bpmn.model.Process;
import org.flowable.task.api.Task;
/** /**
* HazardWorkPlanScheduler - 优化版(版本 B) * HazardWorkPlanScheduler - 优化版(版本 B)
...@@ -46,7 +55,6 @@ import java.util.stream.Collectors; ...@@ -46,7 +55,6 @@ import java.util.stream.Collectors;
@Component @Component
@Slf4j @Slf4j
public class HazardWorkPlanScheduler { public class HazardWorkPlanScheduler {
private static final String DICT_ENABLE_ID = "1"; private static final String DICT_ENABLE_ID = "1";
private static final String DICT_ENABLE_VALUE = "可以执行"; private static final String DICT_ENABLE_VALUE = "可以执行";
...@@ -69,6 +77,12 @@ public class HazardWorkPlanScheduler { ...@@ -69,6 +77,12 @@ public class HazardWorkPlanScheduler {
@Autowired @Autowired
private HistoryService historyService; private HistoryService historyService;
@Autowired
private RepositoryService repositoryService;
@Autowired
private TaskService taskService;
@Autowired @Autowired
private NewSysOrgService orgService; private NewSysOrgService orgService;
...@@ -93,10 +107,10 @@ public class HazardWorkPlanScheduler { ...@@ -93,10 +107,10 @@ public class HazardWorkPlanScheduler {
try { try {
Map<String, SysDictData> typeMap = dictDataService.getDictId(DICT_WORK_TYPE) Map<String, SysDictData> typeMap = dictDataService.getDictId(DICT_WORK_TYPE)
.stream() .stream()
.collect(Collectors.toMap(SysDictData::getDictValue, Function.identity(), (a, b) -> a)); .collect(Collectors.toMap(SysDictData::getDictDataId, Function.identity(), (a, b) -> a));
Map<String, SysDictData> levelMap = dictDataService.getDictId(DICT_WORK_LEVEL) Map<String, SysDictData> levelMap = dictDataService.getDictId(DICT_WORK_LEVEL)
.stream() .stream()
.collect(Collectors.toMap(SysDictData::getDictValue, Function.identity(), (a, b) -> a)); .collect(Collectors.toMap(SysDictData::getDictDataId, Function.identity(), (a, b) -> a));
workTypeCache.clear(); workTypeCache.clear();
workTypeCache.putAll(typeMap); workTypeCache.putAll(typeMap);
...@@ -114,7 +128,7 @@ public class HazardWorkPlanScheduler { ...@@ -114,7 +128,7 @@ public class HazardWorkPlanScheduler {
/** /**
* 每5分钟检查安全许可通过后仍在运行的作业 * 每5分钟检查安全许可通过后仍在运行的作业
*/ */
@Scheduled(cron = "0 0/5 * * * ?") //@Scheduled(cron = "0 0/5 * * * ?")
public void refreshSwitch() { public void refreshSwitch() {
if (!isSchedulerEnabled()) { if (!isSchedulerEnabled()) {
log.debug("refreshSwitch: 调度被禁用(字典值非 {})", DICT_ENABLE_VALUE); log.debug("refreshSwitch: 调度被禁用(字典值非 {})", DICT_ENABLE_VALUE);
...@@ -214,10 +228,10 @@ public class HazardWorkPlanScheduler { ...@@ -214,10 +228,10 @@ public class HazardWorkPlanScheduler {
*/ */
@Transactional @Transactional
public void handleExpiredOperation(THazardWorkPlan plan, public void handleExpiredOperation(THazardWorkPlan plan,
String validationResult, String validationResult,
DangerousOperationValidator.OperationType operationType, DangerousOperationValidator.OperationType operationType,
DangerousOperationValidator.DangerLevel dangerLevel, DangerousOperationValidator.DangerLevel dangerLevel,
double actualHours) { double actualHours) {
log.warn("作业过期 - planId={}, code={}, type={}, level={}, hours={}, reason={}", log.warn("作业过期 - planId={}, code={}, type={}, level={}, hours={}, reason={}",
plan.getId(), plan.getCode(), plan.getId(), plan.getCode(),
...@@ -245,8 +259,8 @@ public class HazardWorkPlanScheduler { ...@@ -245,8 +259,8 @@ public class HazardWorkPlanScheduler {
log.error("插入过期日志失败,planId={}", plan.getId(), e); log.error("插入过期日志失败,planId={}", plan.getId(), e);
} }
// 2) 停止 Flowable 流程 //跳转到安全许可证关闭最后一个节点
stopFlowableProcess(plan); jumpToLastNode(plan.getProcessId());
// 3) 更新业务状态 // 3) 更新业务状态
try { try {
...@@ -282,6 +296,399 @@ public class HazardWorkPlanScheduler { ...@@ -282,6 +296,399 @@ public class HazardWorkPlanScheduler {
return diffMillis / (1000.0 * 60 * 60); return diffMillis / (1000.0 * 60 * 60);
} }
@Transactional
public void jumpToLastNode(String processInstanceId) {
try {
// 1. 获取流程实例
ProcessInstance instance = runtimeService.createProcessInstanceQuery()
.processInstanceId(processInstanceId)
.singleResult();
if (instance == null) {
log.warn("流程实例不存在,无法跳转: {}", processInstanceId);
return;
}
// 2. 通过节点名称找到目标节点
String targetActivityId = findUserTaskByName(instance.getProcessDefinitionId(), "安全许可证关闭");
if (targetActivityId == null) {
log.warn("未找到名称为'安全许可证关闭'的节点");
return;
}
log.info("找到目标节点: 安全许可证关闭 (ID: {})", targetActivityId);
// 3. 获取当前任务的处理人
List<Task> currentTasks = taskService.createTaskQuery()
.processInstanceId(processInstanceId)
.list();
if (currentTasks.isEmpty()) {
log.warn("当前没有任务,无法获取处理人: {}", processInstanceId);
return;
}
// 获取处理人
Set<String> assignees = getTaskAssignees(currentTasks, processInstanceId);
if (assignees.isEmpty()) {
log.warn("无法确定任务处理人,使用默认处理人");
// 设置默认处理人
assignees.add(getDefaultAssignee(processInstanceId));
}
log.info("确定的任务处理人: {}", assignees);
// 4. 获取当前执行流
List<Execution> executions = runtimeService.createExecutionQuery()
.processInstanceId(processInstanceId)
.list();
if (executions.isEmpty()) {
log.warn("流程无执行节点,不跳转: {}", processInstanceId);
return;
}
// 5. 准备目标节点所需的流程变量
Map<String, Object> processVariables = prepareProcessVariables(processInstanceId, assignees);
// 6. 使用变更活动状态API跳转,并设置必要的流程变量
ChangeActivityStateBuilder builder = runtimeService.createChangeActivityStateBuilder()
.processInstanceId(processInstanceId);
for (Execution execution : executions) {
if (execution.getActivityId() != null) {
builder.moveExecutionToActivityId(execution.getId(), targetActivityId);
log.info("将执行流 {} 从活动 {} 跳转到 {}",
execution.getId(), execution.getActivityId(), targetActivityId);
}
}
// 设置流程变量,特别是checkUser变量
builder.processVariables(processVariables);
builder.changeState();
// 7. 检查跳转结果
checkJumpResult(processInstanceId, assignees, targetActivityId);
log.info("流程 {} 已成功跳转至'安全许可证关闭'节点,处理人: {}",
processInstanceId, assignees);
} catch (Exception e) {
log.error("跳转到'安全许可证关闭'节点失败,流程实例ID: {}", processInstanceId, e);
throw new RuntimeException("流程跳转失败", e);
}
}
/**
* 获取任务处理人(简化版本,不使用IdentityLink)
*/
private Set<String> getTaskAssignees(List<Task> tasks, String processInstanceId) {
Set<String> assignees = new HashSet<>();
for (Task task : tasks) {
// 1. 首先检查任务是否有直接分配人
if (task.getAssignee() != null && !task.getAssignee().trim().isEmpty()) {
assignees.add(task.getAssignee());
log.info("任务 {} 有分配人: {}", task.getName(), task.getAssignee());
continue;
}
// 2. 如果没有分配人,尝试从任务变量中获取
String potentialAssignee = findAssigneeFromTaskVariables(task.getId());
if (potentialAssignee != null) {
assignees.add(potentialAssignee);
log.info("从任务变量中找到处理人: {}", potentialAssignee);
continue;
}
// 3. 尝试从流程变量中获取
potentialAssignee = findAssigneeFromProcessVariables(processInstanceId);
if (potentialAssignee != null) {
assignees.add(potentialAssignee);
log.info("从流程变量中找到处理人: {}", potentialAssignee);
}
// 4. 如果以上都没有,记录警告
if (assignees.isEmpty()) {
log.warn("任务 {} 没有找到处理人信息", task.getName());
}
}
return assignees;
}
/**
* 从任务变量中查找处理人
*/
private String findAssigneeFromTaskVariables(String taskId) {
try {
Map<String, Object> taskVariables = taskService.getVariables(taskId);
return findAssigneeInVariables(taskVariables);
} catch (Exception e) {
log.warn("从任务变量中查找处理人失败: {}", e.getMessage());
return null;
}
}
/**
* 从流程变量中查找处理人
*/
private String findAssigneeFromProcessVariables(String processInstanceId) {
try {
Map<String, Object> processVariables = runtimeService.getVariables(processInstanceId);
return findAssigneeInVariables(processVariables);
} catch (Exception e) {
log.warn("从流程变量中查找处理人失败: {}", e.getMessage());
return null;
}
}
/**
* 在变量映射中查找处理人
*/
private String findAssigneeInVariables(Map<String, Object> variables) {
if (variables == null) {
return null;
}
// 常见的处理人变量名
String[] potentialAssigneeKeys = {
"assignee", "userId", "currentUser", "starter",
"initiator", "checkUser", "approver", "handler"
};
for (String key : potentialAssigneeKeys) {
Object value = variables.get(key);
if (value != null && !value.toString().trim().isEmpty()) {
return value.toString();
}
}
return null;
}
/**
* 获取默认处理人
*/
private String getDefaultAssignee(String processInstanceId) {
try {
// 尝试获取流程发起人
ProcessInstance instance = runtimeService.createProcessInstanceQuery()
.processInstanceId(processInstanceId)
.singleResult();
if (instance != null && instance.getStartUserId() != null) {
return instance.getStartUserId();
}
// 尝试从流程变量中获取initiator
String initiator = (String) runtimeService.getVariable(processInstanceId, "initiator");
if (initiator != null && !initiator.trim().isEmpty()) {
return initiator;
}
} catch (Exception e) {
log.warn("获取默认处理人失败: {}", e.getMessage());
}
// 返回系统默认用户(请根据实际情况修改)
return "system_admin";
}
/**
* 准备流程变量,特别是目标节点需要的变量
*/
private Map<String, Object> prepareProcessVariables(String processInstanceId, Set<String> assignees) {
Map<String, Object> variables = new HashMap<>();
// 1. 获取现有的流程变量
try {
Map<String, Object> existingVariables = runtimeService.getVariables(processInstanceId);
if (existingVariables != null) {
variables.putAll(existingVariables);
}
} catch (Exception e) {
log.warn("获取现有流程变量失败: {}", e.getMessage());
}
// 2. 设置目标节点需要的checkUser变量
if (!assignees.isEmpty()) {
String checkUser = assignees.iterator().next();
variables.put("checkUser", checkUser);
log.info("设置checkUser变量: {}", checkUser);
} else {
// 如果没有处理人,设置一个默认值
String defaultUser = getDefaultAssignee(processInstanceId);
variables.put("checkUser", defaultUser);
log.warn("没有找到处理人,使用默认值设置checkUser: {}", defaultUser);
}
// 3. 确保其他可能需要的变量存在
ensureRequiredVariables(variables, processInstanceId);
log.info("准备的流程变量: {}", variables.keySet());
return variables;
}
/**
* 确保其他必要变量存在
*/
private void ensureRequiredVariables(Map<String, Object> variables, String processInstanceId) {
// 添加其他可能需要的变量
if (!variables.containsKey("approveResult")) {
variables.put("approveResult", "agree"); // 默认同意
}
// 根据业务需求添加其他必要变量
if (!variables.containsKey("jumpSource")) {
variables.put("jumpSource", "auto_jump_to_last_node");
}
}
/**
* 检查跳转结果
*/
private void checkJumpResult(String processInstanceId, Set<String> assignees, String expectedActivityId) {
// 等待流程引擎处理
try {
for (int i = 0; i < 3; i++) {
Thread.sleep(1000);
List<Task> newTasks = taskService.createTaskQuery()
.processInstanceId(processInstanceId)
.list();
if (!newTasks.isEmpty()) {
processNewTasks(newTasks, assignees, expectedActivityId);
return;
}
log.info("第 {} 次检查,尚未发现新任务", i + 1);
}
log.warn("跳转后长时间未发现新任务");
checkExecutionState(processInstanceId, expectedActivityId);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
/**
* 处理新生成的任务
*/
private void processNewTasks(List<Task> newTasks, Set<String> assignees, String expectedActivityId) {
boolean foundTarget = false;
for (Task task : newTasks) {
String taskDefinitionKey = getTaskDefinitionKey(task);
if (expectedActivityId.equals(taskDefinitionKey)) {
foundTarget = true;
log.info("成功跳转到目标节点: {} ({})", task.getName(), taskDefinitionKey);
// 设置任务分配人(如果任务还没有分配人)
if (task.getAssignee() == null && !assignees.isEmpty()) {
String assignee = assignees.iterator().next();
taskService.setAssignee(task.getId(), assignee);
log.info("为任务 '{}' 设置处理人: {}", task.getName(), assignee);
} else if (task.getAssignee() != null) {
log.info("任务 '{}' 已有处理人: {}", task.getName(), task.getAssignee());
}
break;
}
}
if (!foundTarget) {
log.warn("跳转未到达预期节点。预期: {},实际任务: {}",
expectedActivityId,
newTasks.stream()
.map(t -> t.getName() + "(" + getTaskDefinitionKey(t) + ")")
.collect(Collectors.toList()));
}
}
/**
* 检查执行流状态
*/
private void checkExecutionState(String processInstanceId, String expectedActivityId) {
try {
List<Execution> executions = runtimeService.createExecutionQuery()
.processInstanceId(processInstanceId)
.list();
log.info("当前执行流状态:");
for (Execution exec : executions) {
log.info("执行流: {}, 活动ID: {}", exec.getId(), exec.getActivityId());
}
} catch (Exception e) {
log.warn("检查执行流状态失败: {}", e.getMessage());
}
}
/**
* 获取任务定义Key
*/
private String getTaskDefinitionKey(Task task) {
try {
// 尝试通过反射获取taskDefinitionKey
java.lang.reflect.Method method = task.getClass().getMethod("getTaskDefinitionKey");
Object result = method.invoke(task);
return result != null ? result.toString() : "unknown";
} catch (Exception e) {
// 如果获取失败,返回任务名称作为标识
return task.getName() != null ? task.getName() : "unknown";
}
}
/**
* 通过节点名称查找用户任务
*/
private String findUserTaskByName(String processDefinitionId, String taskName) {
try {
BpmnModel model = repositoryService.getBpmnModel(processDefinitionId);
if (model == null) {
log.error("无法加载 BPMN 模型: {}", processDefinitionId);
return null;
}
Process process = model.getMainProcess();
List<UserTask> matchingTasks = process.getFlowElements().stream()
.filter(element -> element instanceof UserTask)
.map(element -> (UserTask) element)
.filter(task -> taskName.equals(task.getName()))
.collect(Collectors.toList());
if (matchingTasks.isEmpty()) {
log.warn("未找到名称为'{}'的用户任务", taskName);
// 输出所有用户任务名称,用于调试
List<UserTask> allUserTasks = process.getFlowElements().stream()
.filter(element -> element instanceof UserTask)
.map(element -> (UserTask) element)
.collect(Collectors.toList());
if (!allUserTasks.isEmpty()) {
log.info("流程中所有用户任务: {}",
allUserTasks.stream().map(UserTask::getName).collect(Collectors.toList()));
}
return null;
}
if (matchingTasks.size() > 1) {
log.warn("找到多个名称为'{}'的用户任务,将使用第一个", taskName);
matchingTasks.sort(Comparator.comparing(UserTask::getId));
}
UserTask targetTask = matchingTasks.get(0);
log.info("找到目标任务: {} (ID: {})", targetTask.getName(), targetTask.getId());
return targetTask.getId();
} catch (Exception e) {
log.error("查找用户任务失败: {}", e.getMessage());
return null;
}
}
/** /**
* 停止流程(更稳健的实现:先查询流程实例是否存在,再删除运行时并删除历史) * 停止流程(更稳健的实现:先查询流程实例是否存在,再删除运行时并删除历史)
* 内部捕获异常,保证调度器稳定运行。 * 内部捕获异常,保证调度器稳定运行。
...@@ -351,4 +758,6 @@ public class HazardWorkPlanScheduler { ...@@ -351,4 +758,6 @@ public class HazardWorkPlanScheduler {
throw e; throw e;
} }
} }
} }
package com.testor.module.hazard.service.impl; package com.testor.module.hazard.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils; import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.testor.biz.sys.dict.data.model.domain.SysDictData; import com.testor.biz.sys.dict.data.model.domain.SysDictData;
import com.testor.common.core.constant.Constants;
import com.testor.common.util.DangerousOperationValidator; import com.testor.common.util.DangerousOperationValidator;
import com.testor.module.hazard.dao.THazardWorkPlanDao; import com.testor.module.hazard.dao.THazardWorkPlanDao;
import com.testor.module.hazard.dao.THazardWorkPlanExpiredLogDao; import com.testor.module.hazard.dao.THazardWorkPlanExpiredLogDao;
...@@ -10,12 +12,23 @@ import com.testor.module.hazard.model.domain.THazardWorkPlan; ...@@ -10,12 +12,23 @@ import com.testor.module.hazard.model.domain.THazardWorkPlan;
import com.testor.module.hazard.model.domain.THazardWorkPlanExpiredLog; import com.testor.module.hazard.model.domain.THazardWorkPlanExpiredLog;
import com.testor.module.hazard.model.enums.WorkPlanStatusEnum; import com.testor.module.hazard.model.enums.WorkPlanStatusEnum;
import com.testor.module.hazard.service.THazardWorkPlanExpiredLogService; import com.testor.module.hazard.service.THazardWorkPlanExpiredLogService;
import com.testor.module.sys.model.domian.NewSysOrg;
import com.testor.module.sys.service.NewSysDictDataService; import com.testor.module.sys.service.NewSysDictDataService;
import com.testor.module.sys.service.NewSysOrgService;
import com.tongtech.tfw.backend.common.models.supers.SuperServiceImpl; import com.tongtech.tfw.backend.common.models.supers.SuperServiceImpl;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.flowable.bpmn.model.BpmnModel;
import org.flowable.bpmn.model.FlowElement;
import org.flowable.bpmn.model.Process;
import org.flowable.bpmn.model.UserTask;
import org.flowable.engine.HistoryService; import org.flowable.engine.HistoryService;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService; import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.runtime.ChangeActivityStateBuilder;
import org.flowable.engine.runtime.Execution;
import org.flowable.engine.runtime.ProcessInstance; import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled; import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
...@@ -23,9 +36,7 @@ import org.springframework.transaction.annotation.Transactional; ...@@ -23,9 +36,7 @@ import org.springframework.transaction.annotation.Transactional;
import javax.annotation.PostConstruct; import javax.annotation.PostConstruct;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.Date; import java.util.*;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Function; import java.util.function.Function;
import java.util.stream.Collectors; import java.util.stream.Collectors;
...@@ -56,6 +67,15 @@ public class THazardWorkPlanExpiredLogServiceImpl extends SuperServiceImpl<THaza ...@@ -56,6 +67,15 @@ public class THazardWorkPlanExpiredLogServiceImpl extends SuperServiceImpl<THaza
@Autowired @Autowired
private HistoryService historyService; private HistoryService historyService;
@Autowired
private RepositoryService repositoryService;
@Autowired
private TaskService taskService;
@Autowired
private NewSysOrgService orgService;
// 缓存:key = dictValue, value = SysDictData // 缓存:key = dictValue, value = SysDictData
private final Map<String, SysDictData> workTypeCache = new ConcurrentHashMap<>(); private final Map<String, SysDictData> workTypeCache = new ConcurrentHashMap<>();
private final Map<String, SysDictData> workLevelCache = new ConcurrentHashMap<>(); private final Map<String, SysDictData> workLevelCache = new ConcurrentHashMap<>();
...@@ -68,6 +88,7 @@ public class THazardWorkPlanExpiredLogServiceImpl extends SuperServiceImpl<THaza ...@@ -68,6 +88,7 @@ public class THazardWorkPlanExpiredLogServiceImpl extends SuperServiceImpl<THaza
/** /**
* 定时刷新字典缓存(每 10 分钟刷新一次,保证字典变更能生效) * 定时刷新字典缓存(每 10 分钟刷新一次,保证字典变更能生效)
*/ */
//@Scheduled(cron = "0 0/10 * * * ?")
public void refreshDictCacheScheduled() { public void refreshDictCacheScheduled() {
refreshDictCache(); refreshDictCache();
} }
...@@ -76,10 +97,10 @@ public class THazardWorkPlanExpiredLogServiceImpl extends SuperServiceImpl<THaza ...@@ -76,10 +97,10 @@ public class THazardWorkPlanExpiredLogServiceImpl extends SuperServiceImpl<THaza
try { try {
Map<String, SysDictData> typeMap = dictDataService.getDictId(DICT_WORK_TYPE) Map<String, SysDictData> typeMap = dictDataService.getDictId(DICT_WORK_TYPE)
.stream() .stream()
.collect(Collectors.toMap(SysDictData::getDictValue, Function.identity(), (a, b) -> a)); .collect(Collectors.toMap(SysDictData::getDictDataId, Function.identity(), (a, b) -> a));
Map<String, SysDictData> levelMap = dictDataService.getDictId(DICT_WORK_LEVEL) Map<String, SysDictData> levelMap = dictDataService.getDictId(DICT_WORK_LEVEL)
.stream() .stream()
.collect(Collectors.toMap(SysDictData::getDictValue, Function.identity(), (a, b) -> a)); .collect(Collectors.toMap(SysDictData::getDictDataId, Function.identity(), (a, b) -> a));
workTypeCache.clear(); workTypeCache.clear();
workTypeCache.putAll(typeMap); workTypeCache.putAll(typeMap);
...@@ -97,6 +118,7 @@ public class THazardWorkPlanExpiredLogServiceImpl extends SuperServiceImpl<THaza ...@@ -97,6 +118,7 @@ public class THazardWorkPlanExpiredLogServiceImpl extends SuperServiceImpl<THaza
/** /**
* 每5分钟检查安全许可通过后仍在运行的作业 * 每5分钟检查安全许可通过后仍在运行的作业
*/ */
//@Scheduled(cron = "0 0/5 * * * ?")
@Override @Override
public void refreshSwitch() { public void refreshSwitch() {
if (!isSchedulerEnabled()) { if (!isSchedulerEnabled()) {
...@@ -132,9 +154,6 @@ public class THazardWorkPlanExpiredLogServiceImpl extends SuperServiceImpl<THaza ...@@ -132,9 +154,6 @@ public class THazardWorkPlanExpiredLogServiceImpl extends SuperServiceImpl<THaza
log.info("结束---refreshSwitch-----查询所有危险作业已安全许可申请审批通过后未完成的作业"); log.info("结束---refreshSwitch-----查询所有危险作业已安全许可申请审批通过后未完成的作业");
} }
/**************************** /****************************
* 核心处理函数 * 核心处理函数
****************************/ ****************************/
...@@ -175,6 +194,12 @@ public class THazardWorkPlanExpiredLogServiceImpl extends SuperServiceImpl<THaza ...@@ -175,6 +194,12 @@ public class THazardWorkPlanExpiredLogServiceImpl extends SuperServiceImpl<THaza
return; return;
} }
NewSysOrg org = orgService.getOne(new QueryWrapper<NewSysOrg>().eq("org_id", plan.getOrgId()));
if(org.getParentIds().contains(Constants.DBGK_ORG_ID) || org.getOrgId().equals(Constants.DBGK_ORG_ID)){
plan.setBl(true);
}else{
plan.setBl(false);
}
// 计算从审批通过到现在的小时数 // 计算从审批通过到现在的小时数
double actualHours = calculateHoursBetween(plan.getHazardLicensePassTime()); double actualHours = calculateHoursBetween(plan.getHazardLicensePassTime());
...@@ -225,8 +250,8 @@ public class THazardWorkPlanExpiredLogServiceImpl extends SuperServiceImpl<THaza ...@@ -225,8 +250,8 @@ public class THazardWorkPlanExpiredLogServiceImpl extends SuperServiceImpl<THaza
log.error("插入过期日志失败,planId={}", plan.getId(), e); log.error("插入过期日志失败,planId={}", plan.getId(), e);
} }
// 2) 停止 Flowable 流程 //跳转到安全许可证关闭最后一个节点
stopFlowableProcess(plan); jumpToLastNode(plan.getProcessId());
// 3) 更新业务状态 // 3) 更新业务状态
try { try {
...@@ -236,41 +261,6 @@ public class THazardWorkPlanExpiredLogServiceImpl extends SuperServiceImpl<THaza ...@@ -236,41 +261,6 @@ public class THazardWorkPlanExpiredLogServiceImpl extends SuperServiceImpl<THaza
} }
} }
private void handleThreeDaysExpired(THazardWorkPlan plan, double actualHours) {
log.warn("3天过期 - planId={}, code={}, hoursSinceCreation={}",
plan.getId(), plan.getCode(), actualHours);
// 记录日志
try {
THazardWorkPlanExpiredLog expiredLog = new THazardWorkPlanExpiredLog();
expiredLog.setPlanId(plan.getId());
expiredLog.setCode(plan.getCode());
expiredLog.setWorkType(plan.getWorkType());
expiredLog.setDangerLevel(plan.getWorkLevel());
expiredLog.setExpiredReason("作业创建后3天内未完成,需要重新发起申请");
expiredLog.setBeforeExpiration(plan.getWorkStatus());
expiredLog.setHazardLicensePassTime(plan.getHazardLicensePassTime());
expiredLog.setActualDurationHours(BigDecimal.valueOf(actualHours));
expiredLog.setPlanCreateDate(plan.getCreateDate());
expiredLog.setStatus("0");
expiredLog.setCreateBy("system-relaxed");
expiredLog.setCreateDate(new Date());
hazardWorkPlanExpiredLogDao.insert(expiredLog);
} catch (Exception e) {
log.error("记录3天过期日志失败,planId={}", plan.getId(), e);
}
// 停止流程并更新状态
stopFlowableProcess(plan);
try {
// 更新状态
updateOperationStatus(plan, WorkPlanStatusEnum.TIMEOUT_CANCELED.getValue());
} catch (Exception e) {
log.error("3天过期后更新作业状态失败,planId={}", plan.getId(), e);
}
}
/** /**
* 检查调度是否启用(通过字典开关) * 检查调度是否启用(通过字典开关)
*/ */
...@@ -297,6 +287,399 @@ public class THazardWorkPlanExpiredLogServiceImpl extends SuperServiceImpl<THaza ...@@ -297,6 +287,399 @@ public class THazardWorkPlanExpiredLogServiceImpl extends SuperServiceImpl<THaza
return diffMillis / (1000.0 * 60 * 60); return diffMillis / (1000.0 * 60 * 60);
} }
@Transactional
public void jumpToLastNode(String processInstanceId) {
try {
// 1. 获取流程实例
ProcessInstance instance = runtimeService.createProcessInstanceQuery()
.processInstanceId(processInstanceId)
.singleResult();
if (instance == null) {
log.warn("流程实例不存在,无法跳转: {}", processInstanceId);
return;
}
// 2. 通过节点名称找到目标节点
String targetActivityId = findUserTaskByName(instance.getProcessDefinitionId(), "安全许可证关闭");
if (targetActivityId == null) {
log.warn("未找到名称为'安全许可证关闭'的节点");
return;
}
log.info("找到目标节点: 安全许可证关闭 (ID: {})", targetActivityId);
// 3. 获取当前任务的处理人
List<Task> currentTasks = taskService.createTaskQuery()
.processInstanceId(processInstanceId)
.list();
if (currentTasks.isEmpty()) {
log.warn("当前没有任务,无法获取处理人: {}", processInstanceId);
return;
}
// 获取处理人
Set<String> assignees = getTaskAssignees(currentTasks, processInstanceId);
if (assignees.isEmpty()) {
log.warn("无法确定任务处理人,使用默认处理人");
// 设置默认处理人
assignees.add(getDefaultAssignee(processInstanceId));
}
log.info("确定的任务处理人: {}", assignees);
// 4. 获取当前执行流
List<Execution> executions = runtimeService.createExecutionQuery()
.processInstanceId(processInstanceId)
.list();
if (executions.isEmpty()) {
log.warn("流程无执行节点,不跳转: {}", processInstanceId);
return;
}
// 5. 准备目标节点所需的流程变量
Map<String, Object> processVariables = prepareProcessVariables(processInstanceId, assignees);
// 6. 使用变更活动状态API跳转,并设置必要的流程变量
ChangeActivityStateBuilder builder = runtimeService.createChangeActivityStateBuilder()
.processInstanceId(processInstanceId);
for (Execution execution : executions) {
if (execution.getActivityId() != null) {
builder.moveExecutionToActivityId(execution.getId(), targetActivityId);
log.info("将执行流 {} 从活动 {} 跳转到 {}",
execution.getId(), execution.getActivityId(), targetActivityId);
}
}
// 设置流程变量,特别是checkUser变量
builder.processVariables(processVariables);
builder.changeState();
// 7. 检查跳转结果
checkJumpResult(processInstanceId, assignees, targetActivityId);
log.info("流程 {} 已成功跳转至'安全许可证关闭'节点,处理人: {}",
processInstanceId, assignees);
} catch (Exception e) {
log.error("跳转到'安全许可证关闭'节点失败,流程实例ID: {}", processInstanceId, e);
throw new RuntimeException("流程跳转失败", e);
}
}
/**
* 获取任务处理人(简化版本,不使用IdentityLink)
*/
private Set<String> getTaskAssignees(List<Task> tasks, String processInstanceId) {
Set<String> assignees = new HashSet<>();
for (Task task : tasks) {
// 1. 首先检查任务是否有直接分配人
if (task.getAssignee() != null && !task.getAssignee().trim().isEmpty()) {
assignees.add(task.getAssignee());
log.info("任务 {} 有分配人: {}", task.getName(), task.getAssignee());
continue;
}
// 2. 如果没有分配人,尝试从任务变量中获取
String potentialAssignee = findAssigneeFromTaskVariables(task.getId());
if (potentialAssignee != null) {
assignees.add(potentialAssignee);
log.info("从任务变量中找到处理人: {}", potentialAssignee);
continue;
}
// 3. 尝试从流程变量中获取
potentialAssignee = findAssigneeFromProcessVariables(processInstanceId);
if (potentialAssignee != null) {
assignees.add(potentialAssignee);
log.info("从流程变量中找到处理人: {}", potentialAssignee);
}
// 4. 如果以上都没有,记录警告
if (assignees.isEmpty()) {
log.warn("任务 {} 没有找到处理人信息", task.getName());
}
}
return assignees;
}
/**
* 从任务变量中查找处理人
*/
private String findAssigneeFromTaskVariables(String taskId) {
try {
Map<String, Object> taskVariables = taskService.getVariables(taskId);
return findAssigneeInVariables(taskVariables);
} catch (Exception e) {
log.warn("从任务变量中查找处理人失败: {}", e.getMessage());
return null;
}
}
/**
* 从流程变量中查找处理人
*/
private String findAssigneeFromProcessVariables(String processInstanceId) {
try {
Map<String, Object> processVariables = runtimeService.getVariables(processInstanceId);
return findAssigneeInVariables(processVariables);
} catch (Exception e) {
log.warn("从流程变量中查找处理人失败: {}", e.getMessage());
return null;
}
}
/**
* 在变量映射中查找处理人
*/
private String findAssigneeInVariables(Map<String, Object> variables) {
if (variables == null) {
return null;
}
// 常见的处理人变量名
String[] potentialAssigneeKeys = {
"assignee", "userId", "currentUser", "starter",
"initiator", "checkUser", "approver", "handler"
};
for (String key : potentialAssigneeKeys) {
Object value = variables.get(key);
if (value != null && !value.toString().trim().isEmpty()) {
return value.toString();
}
}
return null;
}
/**
* 获取默认处理人
*/
private String getDefaultAssignee(String processInstanceId) {
try {
// 尝试获取流程发起人
ProcessInstance instance = runtimeService.createProcessInstanceQuery()
.processInstanceId(processInstanceId)
.singleResult();
if (instance != null && instance.getStartUserId() != null) {
return instance.getStartUserId();
}
// 尝试从流程变量中获取initiator
String initiator = (String) runtimeService.getVariable(processInstanceId, "initiator");
if (initiator != null && !initiator.trim().isEmpty()) {
return initiator;
}
} catch (Exception e) {
log.warn("获取默认处理人失败: {}", e.getMessage());
}
// 返回系统默认用户(请根据实际情况修改)
return "system_admin";
}
/**
* 准备流程变量,特别是目标节点需要的变量
*/
private Map<String, Object> prepareProcessVariables(String processInstanceId, Set<String> assignees) {
Map<String, Object> variables = new HashMap<>();
// 1. 获取现有的流程变量
try {
Map<String, Object> existingVariables = runtimeService.getVariables(processInstanceId);
if (existingVariables != null) {
variables.putAll(existingVariables);
}
} catch (Exception e) {
log.warn("获取现有流程变量失败: {}", e.getMessage());
}
// 2. 设置目标节点需要的checkUser变量
if (!assignees.isEmpty()) {
String checkUser = assignees.iterator().next();
variables.put("checkUser", checkUser);
log.info("设置checkUser变量: {}", checkUser);
} else {
// 如果没有处理人,设置一个默认值
String defaultUser = getDefaultAssignee(processInstanceId);
variables.put("checkUser", defaultUser);
log.warn("没有找到处理人,使用默认值设置checkUser: {}", defaultUser);
}
// 3. 确保其他可能需要的变量存在
ensureRequiredVariables(variables, processInstanceId);
log.info("准备的流程变量: {}", variables.keySet());
return variables;
}
/**
* 确保其他必要变量存在
*/
private void ensureRequiredVariables(Map<String, Object> variables, String processInstanceId) {
// 添加其他可能需要的变量
if (!variables.containsKey("approveResult")) {
variables.put("approveResult", "agree"); // 默认同意
}
// 根据业务需求添加其他必要变量
if (!variables.containsKey("jumpSource")) {
variables.put("jumpSource", "auto_jump_to_last_node");
}
}
/**
* 检查跳转结果
*/
private void checkJumpResult(String processInstanceId, Set<String> assignees, String expectedActivityId) {
// 等待流程引擎处理
try {
for (int i = 0; i < 3; i++) {
Thread.sleep(1000);
List<Task> newTasks = taskService.createTaskQuery()
.processInstanceId(processInstanceId)
.list();
if (!newTasks.isEmpty()) {
processNewTasks(newTasks, assignees, expectedActivityId);
return;
}
log.info("第 {} 次检查,尚未发现新任务", i + 1);
}
log.warn("跳转后长时间未发现新任务");
checkExecutionState(processInstanceId, expectedActivityId);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
/**
* 处理新生成的任务
*/
private void processNewTasks(List<Task> newTasks, Set<String> assignees, String expectedActivityId) {
boolean foundTarget = false;
for (Task task : newTasks) {
String taskDefinitionKey = getTaskDefinitionKey(task);
if (expectedActivityId.equals(taskDefinitionKey)) {
foundTarget = true;
log.info("成功跳转到目标节点: {} ({})", task.getName(), taskDefinitionKey);
// 设置任务分配人(如果任务还没有分配人)
if (task.getAssignee() == null && !assignees.isEmpty()) {
String assignee = assignees.iterator().next();
taskService.setAssignee(task.getId(), assignee);
log.info("为任务 '{}' 设置处理人: {}", task.getName(), assignee);
} else if (task.getAssignee() != null) {
log.info("任务 '{}' 已有处理人: {}", task.getName(), task.getAssignee());
}
break;
}
}
if (!foundTarget) {
log.warn("跳转未到达预期节点。预期: {},实际任务: {}",
expectedActivityId,
newTasks.stream()
.map(t -> t.getName() + "(" + getTaskDefinitionKey(t) + ")")
.collect(Collectors.toList()));
}
}
/**
* 检查执行流状态
*/
private void checkExecutionState(String processInstanceId, String expectedActivityId) {
try {
List<Execution> executions = runtimeService.createExecutionQuery()
.processInstanceId(processInstanceId)
.list();
log.info("当前执行流状态:");
for (Execution exec : executions) {
log.info("执行流: {}, 活动ID: {}", exec.getId(), exec.getActivityId());
}
} catch (Exception e) {
log.warn("检查执行流状态失败: {}", e.getMessage());
}
}
/**
* 获取任务定义Key
*/
private String getTaskDefinitionKey(Task task) {
try {
// 尝试通过反射获取taskDefinitionKey
java.lang.reflect.Method method = task.getClass().getMethod("getTaskDefinitionKey");
Object result = method.invoke(task);
return result != null ? result.toString() : "unknown";
} catch (Exception e) {
// 如果获取失败,返回任务名称作为标识
return task.getName() != null ? task.getName() : "unknown";
}
}
/**
* 通过节点名称查找用户任务
*/
private String findUserTaskByName(String processDefinitionId, String taskName) {
try {
BpmnModel model = repositoryService.getBpmnModel(processDefinitionId);
if (model == null) {
log.error("无法加载 BPMN 模型: {}", processDefinitionId);
return null;
}
Process process = model.getMainProcess();
List<UserTask> matchingTasks = process.getFlowElements().stream()
.filter(element -> element instanceof UserTask)
.map(element -> (UserTask) element)
.filter(task -> taskName.equals(task.getName()))
.collect(Collectors.toList());
if (matchingTasks.isEmpty()) {
log.warn("未找到名称为'{}'的用户任务", taskName);
// 输出所有用户任务名称,用于调试
List<UserTask> allUserTasks = process.getFlowElements().stream()
.filter(element -> element instanceof UserTask)
.map(element -> (UserTask) element)
.collect(Collectors.toList());
if (!allUserTasks.isEmpty()) {
log.info("流程中所有用户任务: {}",
allUserTasks.stream().map(UserTask::getName).collect(Collectors.toList()));
}
return null;
}
if (matchingTasks.size() > 1) {
log.warn("找到多个名称为'{}'的用户任务,将使用第一个", taskName);
matchingTasks.sort(Comparator.comparing(UserTask::getId));
}
UserTask targetTask = matchingTasks.get(0);
log.info("找到目标任务: {} (ID: {})", targetTask.getName(), targetTask.getId());
return targetTask.getId();
} catch (Exception e) {
log.error("查找用户任务失败: {}", e.getMessage());
return null;
}
}
/** /**
* 停止流程(更稳健的实现:先查询流程实例是否存在,再删除运行时并删除历史) * 停止流程(更稳健的实现:先查询流程实例是否存在,再删除运行时并删除历史)
* 内部捕获异常,保证调度器稳定运行。 * 内部捕获异常,保证调度器稳定运行。
...@@ -370,8 +753,13 @@ public class THazardWorkPlanExpiredLogServiceImpl extends SuperServiceImpl<THaza ...@@ -370,8 +753,13 @@ public class THazardWorkPlanExpiredLogServiceImpl extends SuperServiceImpl<THaza
@Override @Override
public THazardWorkPlanExpiredLog selectByPlanId(String planId) { public THazardWorkPlanExpiredLog selectByPlanId(String planId) {
return hazardWorkPlanExpiredLogDao.selectOne(new LambdaQueryWrapper<THazardWorkPlanExpiredLog>() List<THazardWorkPlanExpiredLog> tHazardWorkPlanExpiredLogs = hazardWorkPlanExpiredLogDao.selectList(new LambdaQueryWrapper<THazardWorkPlanExpiredLog>()
.eq(THazardWorkPlanExpiredLog::getPlanId, planId)); .eq(THazardWorkPlanExpiredLog::getPlanId, planId));
if(null != tHazardWorkPlanExpiredLogs && tHazardWorkPlanExpiredLogs.size() > 0){
return tHazardWorkPlanExpiredLogs.get(0);
}else{
return null;
}
} }
} }
...@@ -627,26 +627,32 @@ public class THazardWorkPlanServiceImpl extends SuperServiceImpl<THazardWorkPlan ...@@ -627,26 +627,32 @@ public class THazardWorkPlanServiceImpl extends SuperServiceImpl<THazardWorkPlan
THazardWorkPlan updWorkPlan = new THazardWorkPlan(); THazardWorkPlan updWorkPlan = new THazardWorkPlan();
updWorkPlan.setId(id); updWorkPlan.setId(id);
updWorkPlan.setHazardLicensePassTime(new Date()); //updWorkPlan.setHazardLicensePassTime(new Date());
this.updateById(updWorkPlan); this.updateById(updWorkPlan);
} }
//如果为安全许可证关闭 //如果为安全许可证关闭
if (WorkPlanStatusEnum.TO_BE_CLOSED.getValue().equals(workStatus)) { if (WorkPlanStatusEnum.TO_BE_CLOSED.getValue().equals(workStatus) || WorkPlanStatusEnum.TIMEOUT_CANCELED.getValue().equals(workStatus)) {
//关闭流程 //关闭流程
executionWorkProcess(id, tHazardWorkPlanDTO.getTaskId(), WorkPlanStatusEnum.CLOSED.getValue(), tHazardWorkPlanDTO.getMap(), tHazardWorkPlan); executionWorkProcess(id, tHazardWorkPlanDTO.getTaskId(), WorkPlanStatusEnum.CLOSED.getValue(), tHazardWorkPlanDTO.getMap(), tHazardWorkPlan);
THazardWorkPlan updWorkPlan = new THazardWorkPlan(); THazardWorkPlan updWorkPlan = new THazardWorkPlan();
updWorkPlan.setId(id); updWorkPlan.setId(id);
Date scheduledEndTime = tHazardWorkPlan.getScheduledEndTime(); Date scheduledEndTime = tHazardWorkPlan.getScheduledEndTime();
//如果计划结束时间在当前时间之后 if(WorkPlanStatusEnum.TIMEOUT_CANCELED.getValue().equals(workStatus)){
if (scheduledEndTime.after(new Date())) { updWorkPlan.setWorkStatus(WorkPlanStatusEnum.TIMEOUT_CANCELED.getValue());
//更新状态 取消状态 }else{
updWorkPlan.setWorkStatus(WorkPlanStatusEnum.CLOSED.getValue()); //如果计划结束时间在当前时间之后
} else { if (scheduledEndTime.after(new Date())) {
//更新状态 超时 //更新状态 取消状态
updWorkPlan.setWorkStatus(WorkPlanStatusEnum.OVERDUE.getValue()); updWorkPlan.setWorkStatus(WorkPlanStatusEnum.CLOSED.getValue());
} else {
//更新状态 超时
updWorkPlan.setWorkStatus(WorkPlanStatusEnum.OVERDUE.getValue());
}
} }
//更新结束时间 //更新结束时间
updWorkPlan.setActualEndTime(new Date()); updWorkPlan.setActualEndTime(new Date());
this.updateById(updWorkPlan); this.updateById(updWorkPlan);
......
...@@ -88,6 +88,7 @@ public class DynamicCandidateUsersListener implements TaskListener { ...@@ -88,6 +88,7 @@ public class DynamicCandidateUsersListener implements TaskListener {
String bizId = delegateTask.getVariable("bizKeyId").toString(); String bizId = delegateTask.getVariable("bizKeyId").toString();
THazardWorkPlan byId = tHazardWorkPlanService.getById(bizId); THazardWorkPlan byId = tHazardWorkPlanService.getById(bizId);
if (byId != null){ if (byId != null){
byId.setHazardLicensePassTime(new Date());
byId.setWorkStatus(WorkPlanStatusEnum.TECHNICAL_EXPLANATION.getValue()); byId.setWorkStatus(WorkPlanStatusEnum.TECHNICAL_EXPLANATION.getValue());
tHazardWorkPlanService.updateById(byId); tHazardWorkPlanService.updateById(byId);
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment