package jnpf.flowable.job; import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.util.ObjectUtil; import com.alibaba.fastjson.JSONObject; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import jnpf.base.ActionResult; import jnpf.base.UserInfo; import jnpf.config.ConfigValueUtil; import jnpf.database.util.TenantDataSourceUtil; import jnpf.flowable.entity.OperatorEntity; import jnpf.flowable.entity.RecordEntity; import jnpf.flowable.entity.TaskEntity; import jnpf.flowable.enums.OperatorEnum; import jnpf.flowable.enums.OperatorStateEnum; import jnpf.flowable.model.task.FlowModel; import jnpf.flowable.model.templatenode.nodejson.NodeModel; import jnpf.flowable.model.templatenode.nodejson.TemplateJsonModel; import jnpf.flowable.model.templatenode.nodejson.TimeConfig; import jnpf.flowable.model.time.FlowTimeModel; import jnpf.flowable.service.OperatorService; import jnpf.flowable.service.TaskService; import jnpf.flowable.util.*; import jnpf.permission.entity.UserEntity; import jnpf.util.*; import jnpf.util.context.SpringContext; import lombok.extern.slf4j.Slf4j; import org.quartz.JobExecutionContext; import org.quartz.JobExecutionException; import org.springframework.scheduling.quartz.QuartzJobBean; import java.util.*; import java.util.concurrent.TimeUnit; import java.util.stream.Collectors; /** * 类的描述 * * @author JNPF@YinMai Info. Co., Ltd * @version 5.0.x * @since 2024/12/10 9:17 */ @Slf4j public class AutoTransferJob extends QuartzJobBean { private static RedisUtil redisUtil; private static ConfigValueUtil configValueUtil; private static OperatorService operatorService; private static TaskUtil taskUtil; private static TaskService taskService; private static ServiceUtil serviceUtil; private static MsgUtil msgUtil; private static RedisLock redisLock; private static OperatorUtil operatorUtil; static { redisUtil = SpringContext.getBean(RedisUtil.class); configValueUtil = SpringContext.getBean(ConfigValueUtil.class); operatorService = SpringContext.getBean(OperatorService.class); taskUtil = SpringContext.getBean(TaskUtil.class); taskService = SpringContext.getBean(TaskService.class); serviceUtil = SpringContext.getBean(ServiceUtil.class); msgUtil = SpringContext.getBean(MsgUtil.class); redisLock = SpringContext.getBean(RedisLock.class); operatorUtil = SpringContext.getBean(OperatorUtil.class); } @Override protected void executeInternal(JobExecutionContext context) throws JobExecutionException { List list = FlowJobUtil.getTransfer(redisUtil); if (CollectionUtil.isNotEmpty(list)) { Set nodeCodes = new TreeSet<>(); for (FlowTimeModel timeModel : list) { FlowModel flowModel = timeModel.getFlowModel(); UserInfo userInfo = flowModel.getUserInfo(); if (configValueUtil.isMultiTenancy()) { TenantDataSourceUtil.switchTenant(userInfo.getTenantId()); } String operatorId = timeModel.getOperatorId(); boolean lock = redisLock.lock("transfer-" + operatorId, operatorId, 2, TimeUnit.SECONDS); if (!lock) continue; String nodeCode = flowModel.getNodeCode(); Map formData = flowModel.getFormData(); Map nodes = flowModel.getNodes(); NodeModel nodeModel = nodes.get(nodeCode); TimeConfig config = nodeModel.getOverTimeConfig(); if (ObjectUtil.equals(config.getOverTimeType(), OperatorEnum.Nominator.getCode()) || ObjectUtil.equals(config.getOverTimeType(), OperatorEnum.Serve.getCode())) { if (nodeCodes.contains(flowModel.getNodeCode())) { log.info("自动转审失败,该经办已处理(id:" + operatorId + ",code:" + nodeCode + ")"); FlowJobUtil.removeTransfer(timeModel, redisUtil); continue; } nodeCodes.add(nodeCode); } OperatorEntity operator = operatorService.getById(operatorId); if (null == operator || operator.getHandleStatus() != null) { TimeUtil.deleteJob(timeModel.getId()); FlowJobUtil.remove(timeModel, redisUtil); continue; } if (ObjectUtil.equals(operator.getStatus(), OperatorStateEnum.Transfer.getCode())) { log.info("转审状态的经办,不执行: " + operator.getId()); FlowJobUtil.removeTransfer(timeModel, redisUtil); continue; } // 指派类型的转审,判断整个节点 是否存在转审类型的经办 if (ObjectUtil.equals(config.getOverTimeType(), OperatorEnum.Nominator.getCode()) || ObjectUtil.equals(config.getOverTimeType(), OperatorEnum.Serve.getCode())) { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.lambda().eq(OperatorEntity::getTaskId, operator.getTaskId()).eq(OperatorEntity::getNodeId, operator.getNodeId()) .eq(OperatorEntity::getStatus, OperatorStateEnum.Transfer.getCode()); long count = operatorService.count(queryWrapper); if (count > 0) { log.info("节点存在转审状态的经办,不执行: " + operator.getId() + " " + operator.getNodeId()); FlowJobUtil.removeTransfer(timeModel, redisUtil); continue; } } String userId = operator.getHandleId(); if (!ObjectUtil.equals(userInfo.getUserId(), userId)) { String token = AuthUtil.loginTempUser(userId, userInfo.getTenantId()); userInfo = UserProvider.getUser(token); UserProvider.setLoginUser(userInfo); flowModel.setUserInfo(userInfo); } UserProvider.setLocalLoginUser(userInfo); try { TaskEntity taskEntity = taskService.getById(operator.getTaskId()); if (null == taskEntity) { taskEntity = flowModel.getTaskEntity(); } String handleIds = null; if (ObjectUtil.equals(config.getOverTimeType(), OperatorEnum.Nominator.getCode())) { // 指定人员 // 349057407209541--user if (CollectionUtil.isNotEmpty(config.getReApprovers())) { String handleId = config.getReApprovers().get(0).split("--")[0]; UserEntity userEntity = serviceUtil.getUserInfo(handleId); if (!ObjectUtil.equals(userId, handleId) && null != userEntity && ObjectUtil.equals(userEntity.getEnabledMark(), 1)) { handleIds = handleId; } } if (StringUtil.isNotEmpty(handleIds)) { flowModel.setHandleIds(handleIds); flowModel.setAutoTransferFlag(true); taskService.assign(operator.getTaskId(), flowModel); this.delete(timeModel); operatorUtil.handleOperator(); } } else if (ObjectUtil.equals(config.getOverTimeType(), OperatorEnum.Serve.getCode())) { // 接口 String interfaceId = config.getInterfaceId(); List templateJson = config.getTemplateJson(); if (StringUtil.isNotEmpty(interfaceId)) { RecordEntity record = new RecordEntity(); record.setTaskId(taskEntity.getId()); record.setNodeCode(operator.getNodeCode()); record.setHandleId(operator.getHandleId()); // UserEntity createUser = serviceUtil.getUserInfo(taskEntity.getCreatorUserId()); // UserEntity delegate = StringUtil.isNotEmpty(taskEntity.getDelegateUserId()) ? serviceUtil.getUserInfo(taskEntity.getDelegateUserId()) : null; FlowModel parameterModel = new FlowModel(); parameterModel.setFormData(formData); parameterModel.setRecordEntity(record); parameterModel.setTaskEntity(taskEntity); Map parameterMap = msgUtil.parameterMap(parameterModel, templateJson); ActionResult result = serviceUtil.infoToId(interfaceId, parameterMap); if (Objects.equals(200, result.getCode())) { Object data = result.getData(); if (data instanceof Map) { JSONObject map = new JSONObject((Map) data); List handleId = StringUtil.isNotEmpty(map.getString("handleId")) ? Arrays.asList(map.getString("handleId").split(",")) : new ArrayList<>(); handleId = serviceUtil.getUserName(handleId, true) .stream().map(UserEntity::getId).filter(e -> !ObjectUtil.equals(userId, e)).sorted().collect(Collectors.toList()); handleIds = CollectionUtil.isNotEmpty(handleId) ? handleId.get(0) : null; } } if (StringUtil.isNotEmpty(handleIds)) { flowModel.setHandleIds(handleIds); flowModel.setAutoTransferFlag(true); taskService.assign(operator.getTaskId(), flowModel); this.delete(timeModel); operatorUtil.handleOperator(); } } } else { // 超时审批人,2.同一部门 7.同一角色 3.同一岗位 8.同一分组 UserEntity userEntity = serviceUtil.getUserInfo(userId); if (null != userEntity) { Integer overTimeExtraRule = config.getOverTimeExtraRule(); List userIds = new ArrayList<>(); taskUtil.getByRule(userIds, userEntity, overTimeExtraRule); userIds = serviceUtil.getUserName(userIds, true) .stream().map(UserEntity::getId).filter(e -> !ObjectUtil.equals(userId, e)).sorted().collect(Collectors.toList()); if (CollectionUtil.isNotEmpty(userIds)) { handleIds = userIds.get(0); } } if (StringUtil.isNotEmpty(handleIds)) { flowModel.setHandleIds(handleIds); if (operator.getSignTime() == null) { operator.setSignTime(new Date()); } if (operator.getStartHandleTime() == null) { operator.setStartHandleTime(new Date()); } operatorService.updateById(operator); flowModel.setAutoTransferFlag(true); operatorService.transfer(operatorId, flowModel); this.delete(timeModel); operatorUtil.handleOperator(); } } } catch (Exception e) { log.error("超时自动转审异常", e); this.delete(timeModel); } finally { FlowJobUtil.removeTransfer(timeModel, redisUtil); } } } } private void delete(FlowTimeModel timeModel) { TimeUtil.deleteJob(timeModel.getId()); FlowJobUtil.remove(timeModel, redisUtil); } }