From 059ffd3eac93769e8168254365407aceaff8eb71 Mon Sep 17 00:00:00 2001 From: dimengzhe Date: Fri, 21 Jul 2023 11:49:44 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=E4=BC=98=E5=8C=96=E9=94=80=E5=94=AE?= =?UTF-8?q?=E8=AE=A2=E5=8D=95=E6=8F=90=E4=BA=A4=E5=8A=9E=E7=90=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bussalesorder/BusSalesOrderService.java | 137 ++-- .../anrui/flowable/api/flow2/FlowFeign.java | 34 + .../flowable/api/flow2/FlowFeignback.java | 9 + .../anrui/flowable/biz/flow/FlowableRest.java | 8 +- .../anrui/flowable/biz/flow2/FlowMapper.java | 14 + .../anrui/flowable/biz/flow2/FlowMapper.xml | 4 + .../anrui/flowable/biz/flow2/FlowRest.java | 219 +++++++ .../anrui/flowable/biz/flow2/FlowService.java | 592 ++++++++++++++++++ 8 files changed, 951 insertions(+), 66 deletions(-) create mode 100644 anrui-flowable/anrui-flowable-api/src/main/java/com/yxt/anrui/flowable/api/flow2/FlowFeign.java create mode 100644 anrui-flowable/anrui-flowable-api/src/main/java/com/yxt/anrui/flowable/api/flow2/FlowFeignback.java create mode 100644 anrui-flowable/anrui-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flow2/FlowMapper.java create mode 100644 anrui-flowable/anrui-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flow2/FlowMapper.xml create mode 100644 anrui-flowable/anrui-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flow2/FlowRest.java create mode 100644 anrui-flowable/anrui-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flow2/FlowService.java diff --git a/anrui-buscenter/anrui-buscenter-biz/src/main/java/com/yxt/anrui/buscenter/biz/bussalesorder/BusSalesOrderService.java b/anrui-buscenter/anrui-buscenter-biz/src/main/java/com/yxt/anrui/buscenter/biz/bussalesorder/BusSalesOrderService.java index a6f8573df5..25c131f6bf 100644 --- a/anrui-buscenter/anrui-buscenter-biz/src/main/java/com/yxt/anrui/buscenter/biz/bussalesorder/BusSalesOrderService.java +++ b/anrui-buscenter/anrui-buscenter-biz/src/main/java/com/yxt/anrui/buscenter/biz/bussalesorder/BusSalesOrderService.java @@ -138,6 +138,7 @@ import com.yxt.anrui.fin.api.finuncollectedreceivablesdetailed.UnCollectionDto; import com.yxt.anrui.flowable.api.flow.FlowSelectVo; import com.yxt.anrui.flowable.api.flow.FlowableFeign; import com.yxt.anrui.flowable.api.flow.UpdateFlowFieldVo; +import com.yxt.anrui.flowable.api.flow2.FlowFeign; import com.yxt.anrui.flowable.api.flowtask.FlowTaskFeign; import com.yxt.anrui.flowable.api.flowtask.FlowTaskVo; import com.yxt.anrui.flowable.api.flowtask.FlowableQuery; @@ -252,6 +253,8 @@ public class BusSalesOrderService extends MybatisBaseService voResultBean = flowableFeign.startProcess(bv); + ResultBean voResultBean = flowFeign.startProcess(bv); if (!voResultBean.getSuccess()) { return rb.setMsg(voResultBean.getMsg()); } @@ -4819,7 +4825,7 @@ public class BusSalesOrderService extends MybatisBaseService resultBean = flowableFeign.handleProsess(bv); + ResultBean resultBean = flowFeign.handleProsess(bv); if (!resultBean.getSuccess()) { return rb.setMsg(resultBean.getMsg()); } UpdateFlowFieldVo ufVo = resultBean.getData(); updateFlowFiled(BeanUtil.beanToMap(resultBean.getData())); - + busSalesOrder = fetchBySid(bv.getBusinessSid()); //极光推送 if (!"Event_end".equals(resultBean.getData().getTaskDefKey())) { - //极光推送 - busSalesOrder = fetchBySid(bv.getBusinessSid()); - MessageFlowableQuery messageFlowableQuery = new MessageFlowableQuery(); - MessageFlowVo messageFlowVo = new MessageFlowVo(); - BeanUtil.copyProperties(ufVo, messageFlowVo); - ufVo.setProcInsId(busSalesOrder.getProcInstId()); - messageFlowableQuery.setUfVo(messageFlowVo); - messageFlowableQuery.setAppMap((Map) variables.get("app")); - messageFlowableQuery.setBusinessSid(bv.getBusinessSid()); - messageFlowableQuery.setModuleName("销售订单申请"); - messageFlowableQuery.setMsgContent(busSalesOrder.getStaffName() + "提交的" + messageFlowableQuery.getModuleName() + ",请审批"); - messageFlowableQuery.setMsgTitle("销售订单"); - ResultBean stringResultBean = messageFeign.pushMessage(messageFlowableQuery); + try { + ThreadFactory namedThreadFactory = new ThreadFactoryBuilder() + .setNameFormat("demo-pool-%d").build(); + ExecutorService pool = new ThreadPoolExecutor(2, 100, + 0L, TimeUnit.MILLISECONDS, + new LinkedBlockingQueue(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy()); + BusSalesOrder finalBusSalesOrder = busSalesOrder; + Future future1 = pool.submit(() -> { + //极光推送 + MessageFlowableQuery messageFlowableQuery = new MessageFlowableQuery(); + MessageFlowVo messageFlowVo = new MessageFlowVo(); + BeanUtil.copyProperties(ufVo, messageFlowVo); + ufVo.setProcInsId(finalBusSalesOrder.getProcInstId()); + messageFlowableQuery.setUfVo(messageFlowVo); + messageFlowableQuery.setAppMap((Map) variables.get("app")); + messageFlowableQuery.setBusinessSid(bv.getBusinessSid()); + messageFlowableQuery.setModuleName("销售订单申请"); + messageFlowableQuery.setMsgContent(finalBusSalesOrder.getStaffName() + "提交的" + messageFlowableQuery.getModuleName() + ",请审批"); + messageFlowableQuery.setMsgTitle("销售订单"); + ResultBean stringResultBean = messageFeign.pushMessage(messageFlowableQuery); + }); + } catch (Exception e) { + e.printStackTrace(); + } } else { ResultBean details = getSaleOrderDetails(bv.getBusinessSid()); AppOrderDetailsVo vo = details.getData(); diff --git a/anrui-flowable/anrui-flowable-api/src/main/java/com/yxt/anrui/flowable/api/flow2/FlowFeign.java b/anrui-flowable/anrui-flowable-api/src/main/java/com/yxt/anrui/flowable/api/flow2/FlowFeign.java new file mode 100644 index 0000000000..9e4f439e5f --- /dev/null +++ b/anrui-flowable/anrui-flowable-api/src/main/java/com/yxt/anrui/flowable/api/flow2/FlowFeign.java @@ -0,0 +1,34 @@ +package com.yxt.anrui.flowable.api.flow2; + +import com.yxt.anrui.flowable.api.flow.UpdateFlowFieldVo; +import com.yxt.anrui.flowable.sqloperationsymbol.BusinessVariables; +import com.yxt.common.core.result.ResultBean; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.cloud.openfeign.FeignClient; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.ResponseBody; + +/** + * @description: + * @author: dimengzhe + * @date: 2023/7/20 + **/ +@FeignClient( + contextId = "anrui-flowable-Flow", + name = "anrui-flowable", + path = "v2/flow", + fallback = FlowFeignback.class) +public interface FlowFeign { + + @ApiOperation(value = "启动流程") + @PostMapping(value = "/startProcess") + @ResponseBody + ResultBean startProcess(@RequestBody BusinessVariables dto); + + @ApiOperation(value = "处理流程") + @PostMapping(value = "/handleProsess") + @ResponseBody + ResultBean handleProsess(@RequestBody BusinessVariables bv); +} diff --git a/anrui-flowable/anrui-flowable-api/src/main/java/com/yxt/anrui/flowable/api/flow2/FlowFeignback.java b/anrui-flowable/anrui-flowable-api/src/main/java/com/yxt/anrui/flowable/api/flow2/FlowFeignback.java new file mode 100644 index 0000000000..4c644465b3 --- /dev/null +++ b/anrui-flowable/anrui-flowable-api/src/main/java/com/yxt/anrui/flowable/api/flow2/FlowFeignback.java @@ -0,0 +1,9 @@ +package com.yxt.anrui.flowable.api.flow2; + +/** + * @description: + * @author: dimengzhe + * @date: 2023/7/20 + **/ +public class FlowFeignback { +} diff --git a/anrui-flowable/anrui-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flow/FlowableRest.java b/anrui-flowable/anrui-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flow/FlowableRest.java index c2353ab93b..5eb18271a3 100644 --- a/anrui-flowable/anrui-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flow/FlowableRest.java +++ b/anrui-flowable/anrui-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flow/FlowableRest.java @@ -284,11 +284,9 @@ public class FlowableRest implements FlowableFeign { public ResultBean startProcess(BusinessVariables dto) { log.info("startProcess.dto:{}", dto); ResultBean rb = ResultBean.fireFail(); - if (StringUtils.isBlank(dto.getBusinessSid())) { return rb.setMsg("businessSid 不能为空!"); } - if (dto.getFormVariables() == null) dto.setFormVariables(new HashMap()); Map formVariables = dto.getFormVariables(); @@ -296,20 +294,17 @@ public class FlowableRest implements FlowableFeign { String orgPath = dto.getOrgSidPath(); formVariables.put("createrOrgPath", orgPath);//发起人的组织结构sid } - dto.getFormVariables().put("businessSid", dto.getBusinessSid()); String nextNodeUserSids_ = dto.getNextNodeUserSids(); if (StringUtils.isBlank(nextNodeUserSids_)) { ResultBean nextNodeUserSidsOfCreate = getNextNodeUserSidsOfCreate(dto); boolean success = nextNodeUserSidsOfCreate.getSuccess(); if (!success) { -// return rb.setMsg(nextNodeUserSidsOfCreate.getMsg()); nextNodeUserSids_ = ProcDefEnum.DEFAUL_TADMIN_SID.getProDefId(); } else { nextNodeUserSids_ = nextNodeUserSidsOfCreate.getData().getUserSid(); dto.getFormVariables().put(BusinessVariables.ORGPATH, nextNodeUserSidsOfCreate.getData().getOrgPath()); } - } dto.setNextNodeUserSids(nextNodeUserSids_); ResultBean resultBean1 = flowableService.businessStart(dto); @@ -431,7 +426,7 @@ public class FlowableRest implements FlowableFeign { //若下一环节用户与系统管理员一致,则自动审批 if (ProcDefEnum.DEFAUL_TADMIN_SID.getProDefId().equals(nextUserSid)) { adminContains = true; - }else{ + } else { //下一环节不为空,查询下一环节用户是否有转办人 if (nextUserSid != null) { List nextUserList = Arrays.asList(nextUserSid.split(",")); @@ -531,6 +526,7 @@ public class FlowableRest implements FlowableFeign { dto.setTaskId(vo.getTaskId()); dto.setTaskDefKey(taskDefKey); dto.setComment("系统自动跳过"); + dto.setNextNodeUserSids(""); return handleProsess(dto, false); } List flowElements = processService.calApprovePath(dto.getModelId(), dto.getModelId(), diff --git a/anrui-flowable/anrui-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flow2/FlowMapper.java b/anrui-flowable/anrui-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flow2/FlowMapper.java new file mode 100644 index 0000000000..75a54ab80c --- /dev/null +++ b/anrui-flowable/anrui-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flow2/FlowMapper.java @@ -0,0 +1,14 @@ +package com.yxt.anrui.flowable.biz.flow2; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.yxt.anrui.flowable.api.flow.Flowable; +import org.apache.ibatis.annotations.Mapper; + +/** + * @description: + * @author: dimengzhe + * @date: 2023/7/20 + **/ +@Mapper +public interface FlowMapper extends BaseMapper { +} diff --git a/anrui-flowable/anrui-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flow2/FlowMapper.xml b/anrui-flowable/anrui-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flow2/FlowMapper.xml new file mode 100644 index 0000000000..155d9f2b05 --- /dev/null +++ b/anrui-flowable/anrui-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flow2/FlowMapper.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/anrui-flowable/anrui-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flow2/FlowRest.java b/anrui-flowable/anrui-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flow2/FlowRest.java new file mode 100644 index 0000000000..0df8db0cf7 --- /dev/null +++ b/anrui-flowable/anrui-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flow2/FlowRest.java @@ -0,0 +1,219 @@ +package com.yxt.anrui.flowable.biz.flow2; + +import cn.hutool.core.bean.BeanUtil; +import com.alibaba.fastjson.JSONObject; +import com.google.common.util.concurrent.ThreadFactoryBuilder; +import com.yxt.anrui.flowable.api.flow.UpdateFlowFieldVo; +import com.yxt.anrui.flowable.api.flow2.FlowFeign; +import com.yxt.anrui.flowable.biz.process.ProcessService; +import com.yxt.anrui.flowable.feign.MessageFeign; +import com.yxt.anrui.flowable.feign.form.MessageFlowVo; +import com.yxt.anrui.flowable.feign.form.MessageFlowableQuery; +import com.yxt.anrui.flowable.sqloperationsymbol.BusinessVariables; +import com.yxt.anrui.portal.api.sysflowcc.SysFlowccFeign; +import com.yxt.anrui.portal.api.sysflowcc.SysFlowccVo; +import com.yxt.anrui.portal.api.sysuser.SysUserFeign; +import com.yxt.anrui.portal.api.sysuser.SysUserVo; +import com.yxt.anrui.portal.api.sysuser.UserByRolesAndOrgQuery; +import com.yxt.common.base.utils.StringUtils; +import com.yxt.common.core.result.ResultBean; +import org.apache.tomcat.util.threads.ThreadPoolExecutor; +import org.flowable.engine.HistoryService; +import org.flowable.task.api.history.HistoricTaskInstance; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.concurrent.*; + +/** + * @description: + * @author: dimengzhe + * @date: 2023/7/20 + **/ +@RestController +@RequestMapping("v2/flow") +public class FlowRest implements FlowFeign { + Logger log = LoggerFactory.getLogger(FlowRest.class); + + @Autowired + private FlowService flowService; + @Autowired + private SysFlowccFeign sysFlowccFeign; + @Autowired + private SysUserFeign sysUserFeign; + + @Autowired + protected HistoryService historyService; + + @Autowired + private ProcessService processService; + + @Autowired + private MessageFeign messageFeign; + + @Override + public ResultBean startProcess(BusinessVariables bv) { + ResultBean rb = ResultBean.fireFail(); + //获取表单中的参数 + Map formVariables = bv.getFormVariables(); + formVariables = formVariables == null ? new HashMap<>() : formVariables; + //发起人的组织全路径 + String orgPath = bv.getOrgSidPath(); + formVariables.put("createrOrgPath", orgPath); + formVariables.put("businessSid", bv.getBusinessSid()); + //获取下一环节待办人 + ResultBean userResultBean = flowService.getNextNodeUser(bv); + bv.setNextNodeUserSids(userResultBean.getData()); + //启动流程实例 + ResultBean startResultBean = flowService.businessStartProcessInstanceById(bv); + return startResultBean; + } + + @Override + public ResultBean handleProsess(BusinessVariables bv) { + ResultBean rb = ResultBean.fireFail(); + ResultBean updateFlowFieldVoResultBean = flowService.handleProsess(bv, true); + //添加抄送 + log.info("流程返回:{}", JSONObject.toJSONString(updateFlowFieldVoResultBean)); + //需要判断办结后再执行 TODO + if (updateFlowFieldVoResultBean.getSuccess()) { + log.info("流程返回:{}", JSONObject.toJSONString(updateFlowFieldVoResultBean)); + if ("Event_end".equals(updateFlowFieldVoResultBean.getData().getTaskDefKey())) { + try { + ThreadFactory namedThreadFactory = new ThreadFactoryBuilder() + .setNameFormat("demo-pool-%d").build(); + ExecutorService pool = new ThreadPoolExecutor(2, 100, + 0L, TimeUnit.MILLISECONDS, + new LinkedBlockingQueue(1024), namedThreadFactory, new ThreadPoolExecutor.AbortPolicy()); + + Future future1 = pool.submit(() -> { + HashMap map = new HashMap<>(); + map.put("bv", bv); + UpdateFlowFieldVo ufVo = updateFlowFieldVoResultBean.getData(); + ufVo.setTaskId(bv.getTaskId()); + map.put("uff", ufVo); + cc(map, bv.getTaskDefKey()); + }); + } catch (Exception e) { + e.printStackTrace(); + return rb.setMsg("抄送失败"); + } + } + } + return updateFlowFieldVoResultBean; + } + + /** + * 流程抄送的功能 + * + * @param map + * @return + */ + public ResultBean cc(Map map, String taskDefKey) { + ResultBean rb = ResultBean.fireFail(); + log.info("FlowableRest-cc:{}", JSONObject.toJSONString(map)); + Object bv1 = map.get("bv"); + BusinessVariables bv = new BusinessVariables(); + BeanUtil.copyProperties(bv1, bv); + Object uff1 = map.get("uff"); + UpdateFlowFieldVo uff = new UpdateFlowFieldVo(); + BeanUtil.copyProperties(uff1, uff); + uff.setTaskDefKey(taskDefKey); + + //流程定义的id + String modelId = bv.getModelId(); + //将modelId根据冒号:分成三部分,取第一部分作为key + List stringList = Arrays.asList(modelId.split(":")); + modelId = stringList.get(0); + //抄送的角色的sid + ResultBean roleSidByModelId = sysFlowccFeign.getRoleSidByModelId(modelId); + //组织机构sid + String orgSidPath = bv.getOrgSidPath(); + if (roleSidByModelId.getData() == null) { + log.info("抄送失败,没有配置对应的角色!"); + return rb.setMsg("抄送失败,没有配置对应的角色!"); + } + SysFlowccVo data = roleSidByModelId.getData(); + if (StringUtils.isBlank(data.getRoleSid())) { + log.info("抄送失败,没有配置对应的角色!"); + return rb.setMsg("抄送失败,没有配置对应的角色!"); + } + List list = Arrays.asList(data.getRoleSid().split(",")); + UserByRolesAndOrgQuery userQuery = new UserByRolesAndOrgQuery(); + userQuery.setRoleSids(list); + userQuery.setOrgSidPath(orgSidPath); + List sysUserVos = sysUserFeign.getUserByRoles(userQuery).getData(); + if (sysUserVos == null || sysUserVos.size() < 1) { + log.info("抄送失败,没有用户!"); + return rb.setMsg("抄送失败,没有用户!"); + } + StringBuilder userName = new StringBuilder(); + StringBuilder userSids = new StringBuilder(); + sysUserVos.forEach(f -> { + userName.append(f.getName()).append(","); + userSids.append(f.getSid()).append(","); + }); + + //抄送的业务逻辑 + MessageFlowableQuery mfq = new MessageFlowableQuery(); + MessageFlowVo messageFlowVo = new MessageFlowVo(); + BeanUtil.copyProperties(uff, messageFlowVo); + mfq.setUfVo(messageFlowVo); + //移动端的参数 + HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery() + .includeProcessVariables().taskId(bv.getTaskId()).singleResult(); + if (historicTaskInstance == null) { + log.info("抄送失败:没有获取到业务参数!"); + return rb.setMsg("抄送失败!"); + } + Map processVariables = historicTaskInstance.getProcessVariables(); + String createrOrgPath = (String) processVariables.get("createrOrgPath"); + if (historicTaskInstance == null) { + log.info("抄送失败:没有获取到业务参数!"); + return rb.setMsg("抄送失败!"); + } + Map app = new HashMap<>(); + if (processVariables.get("app") != null) { + app = (Map) processVariables.get("app"); + } + log.info("抄送方法-historicTaskInstance:{}", JSONObject.toJSONString(historicTaskInstance)); + mfq.setAppMap(app); + mfq.setBusinessSid(bv.getBusinessSid()); + + mfq.setMsgContent("系统抄送的流程审批,请查看"); +// act_re_procdef + Map process = processService.getProcessDefByDefId(historicTaskInstance.getProcessDefinitionId()); + log.info("抄送成功-process:{}", process); + if (process == null) { + log.info("抄送失败,流程定义不存在!"); + return rb.setMsg("抄送失败,流程定义不存在!"); + } + mfq.setModuleName(process.get("NAME_")); + if (processVariables.containsKey("orderNames")) { + mfq.setMsgTitle(processVariables.get("orderNames").toString()); + } else { + mfq.setMsgTitle(process.get("NAME_")); + } + if (processVariables.containsKey("sendRecommendSid")) {//增加的其他的抄送人 + userSids.append(processVariables.get("sendRecommendSid").toString()).append(","); + } + userSids.deleteCharAt(userSids.length() - 1); + mfq.setUserSids(userSids.toString()); + mfq.setOrgPath(createrOrgPath); + ResultBean resultBean = messageFeign.pushMessageCC(mfq); + log.info("抄送成功:{}", userName.toString()); + log.info("抄送成功-resultBean:{}", resultBean); + if (!resultBean.getSuccess()) { + log.info("抄送失败,同送消息异常!:{}", JSONObject.toJSONString(resultBean)); + return rb.setMsg("抄送失败,同送消息异常!"); + } + return rb.success().setMsg("抄送" + userName.toString() + "成功!"); + } +} diff --git a/anrui-flowable/anrui-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flow2/FlowService.java b/anrui-flowable/anrui-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flow2/FlowService.java new file mode 100644 index 0000000000..8349c2bee1 --- /dev/null +++ b/anrui-flowable/anrui-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flow2/FlowService.java @@ -0,0 +1,592 @@ +package com.yxt.anrui.flowable.biz.flow2; + +import com.alibaba.fastjson.JSON; +import com.alibaba.fastjson.JSONArray; +import com.alibaba.fastjson.JSONObject; +import com.yxt.anrui.flowable.api.flow.Flowable; +import com.yxt.anrui.flowable.api.flow.UpdateFlowFieldVo; +import com.yxt.anrui.flowable.api.flowcomment.FlowComment; +import com.yxt.anrui.flowable.api.flowtask.FlowTask; +import com.yxt.anrui.flowable.api.flowtask.LatestTaskVo; +import com.yxt.anrui.flowable.api.processcomment.ProcessCommentDto; +import com.yxt.anrui.flowable.api.utils.ProcDefEnum; +import com.yxt.anrui.flowable.biz.flowtask.FlowTaskService; +import com.yxt.anrui.flowable.biz.process.ExpressionCmd; +import com.yxt.anrui.flowable.biz.processcomment.ProcessCommentService; +import com.yxt.anrui.flowable.common.ProcessConstants; +import com.yxt.anrui.flowable.sqloperationsymbol.BusinessVariables; +import com.yxt.anrui.portal.api.sysflowableconfig.SysFlowableConfigFeign; +import com.yxt.anrui.portal.api.sysflowableconfig.SysFlowableConfigQuery; +import com.yxt.anrui.portal.api.sysflowableconfig.SysFlowableConfigVvo; +import com.yxt.anrui.portal.api.sysuser.SysUserFeign; +import com.yxt.anrui.portal.api.sysuser.SysUserVo; +import com.yxt.anrui.portal.api.sysuser.UserQuery; +import com.yxt.anrui.portal.api.sysuser.UserssQuery; +import com.yxt.common.base.service.MybatisBaseService; +import com.yxt.common.base.utils.StringUtils; +import com.yxt.common.core.result.ResultBean; +import lombok.extern.slf4j.Slf4j; +import org.flowable.bpmn.model.*; +import org.flowable.engine.*; +import org.flowable.engine.impl.cfg.ProcessEngineConfigurationImpl; +import org.flowable.engine.repository.ProcessDefinition; +import org.flowable.engine.runtime.ProcessInstance; +import org.flowable.task.api.DelegationState; +import org.flowable.task.api.Task; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.*; + +/** + * @description: + * @author: dimengzhe + * @date: 2023/7/20 + **/ +@Service +@Slf4j +public class FlowService extends MybatisBaseService { + + @Autowired + RepositoryService repositoryService; + @Autowired + RuntimeService runtimeService; + + @Autowired + ManagementService managementService; + @Autowired + ProcessEngineConfigurationImpl processEngineConfiguration; + @Autowired + private SysUserFeign sysUserFeign; + + @Autowired + protected IdentityService identityService; + @Autowired + protected TaskService taskService; + @Autowired + private SysFlowableConfigFeign sysFlowableConfigFeign; + @Autowired + private FlowTaskService flowTaskService; + @Autowired + private ProcessCommentService processCommentService; + + public ResultBean getNextNodeUser(BusinessVariables bv) { + ResultBean rb = ResultBean.fireFail(); + //根据业务参数取流程流转的环节 信息 + List> list = (List>) getProcessCirculationNodesByMap(bv).getData(); + if (list == null || list.size() < 2) { + return rb.setMsg("流程设计问题"); + } + //取第二个环节的配置角色 + Object o = list.get(1).get("candidateGroups"); + if (o == null) { + return rb.setMsg("流程设计问题"); + } + JSONArray jsonArray = JSONArray.parseArray(JSON.toJSONString(o)); + String roleSid = jsonArray.get(0).toString(); + //根据组织架构、角色两个参数取相关符合条件的用户信息 + UserQuery userQuery = new UserQuery(); + userQuery.setRoleSid(roleSid); + userQuery.setOrgSidPath(bv.getOrgSidPath()); + String nextNodeUserSids_ = ""; + List sysUserVos = sysUserFeign.getUserByRole(userQuery).getData(); + if (sysUserVos == null || sysUserVos.size() < 1) { + nextNodeUserSids_ = ProcDefEnum.DEFAUL_TADMIN_SID.getProDefId(); + } else { + StringBuilder nextNodeUserSids = new StringBuilder(); + for (SysUserVo su : sysUserVos) { + nextNodeUserSids.append(su.getSid()).append(","); + } + //符合条件的用户的sid,拼接的字符串 + nextNodeUserSids_ = nextNodeUserSids.toString(); + nextNodeUserSids_ = nextNodeUserSids_.substring(0, nextNodeUserSids_.length() - 1); + } + return rb.success().setData(nextNodeUserSids_); + + } + + public ResultBean getProcessCirculationNodesByMap(BusinessVariables bv) { + ResultBean>> rb = new ResultBean>>(); + String modelId = bv.getModelId(); + List flowElements = calApprovePath(modelId, bv.getFormVariables()); + List> list = new ArrayList<>(); + for (FlowElement f : flowElements) { + Map map = new HashMap<>(); + map.put("name", f.getName()); + map.put("id", f.getId()); + String s = JSON.toJSONString(f); + JSONObject jsonObject = JSONObject.parseObject(s); + log.info("item:{}", jsonObject); + Object candidateGroups = jsonObject.get("candidateGroups"); + map.put("candidateGroups", candidateGroups); + list.add(map); + } +// List> list= JSON.parseObject(JSON.toJSONString(flowElements), new TypeReference>>() {}); + return rb.setData(list); + } + + /** + * 1. 首先拿到BpmnModel,所有流程定义信息都可以通过BpmnModel获取;若流程尚未发起,则用modelId查询最新部署的流程定义数据; + * 若流程已经发起,可以通过流程实例的processDefinitionId查询流程定义的历史数据。 + * + * @param variableMap 流程变量,用于计算条件分支 + */ + public List calApprovePath(String modelId, Map variableMap) { + BpmnModel bpmnModel = repositoryService.getBpmnModel(modelId); + Collection flowElements = new ArrayList<>(); + Collection flowElements2 = bpmnModel.getMainProcess().getFlowElements(); + flowElements.addAll(flowElements2); + List passElements = new ArrayList<>(); + dueStartElement(passElements, flowElements, variableMap); + return passElements; + } + + /** + * 2. 找到开始节点,通过它的目标节点,然后再不断往下找。 + */ + private void dueStartElement(List passElements, Collection flowElements, Map variableMap) { + Optional startElementOpt = flowElements.stream().filter(flowElement -> flowElement instanceof StartEvent).findFirst(); + startElementOpt.ifPresent(startElement -> { + flowElements.remove(startElement); + List outgoingFlows = ((StartEvent) startElement).getOutgoingFlows(); + String targetRef = outgoingFlows.get(0).getTargetRef(); + // 根据ID找到FlowElement + FlowElement targetElementOfStartElement = getFlowElement(flowElements, targetRef); + if (targetElementOfStartElement instanceof UserTask) { + this.getPassElementList(passElements, flowElements, targetElementOfStartElement, variableMap); + } + }); + } + + /** + * 3. 我只用到了UserTask、ExclusiveGateway、ParallelGateway,所以代码里只列举了这三种,如果用到了其他的,可以再自己补充 + */ + private void getPassElementList(List passElements, Collection flowElements, FlowElement curFlowElement, Map variableMap) { + // 任务节点 + if (curFlowElement instanceof UserTask) { + this.dueUserTaskElement(passElements, flowElements, curFlowElement, variableMap); + return; + } + // 排他网关 + if (curFlowElement instanceof ExclusiveGateway) { + this.dueExclusiveGateway(passElements, flowElements, curFlowElement, variableMap); + return; + } + // 并行网关 + if (curFlowElement instanceof ParallelGateway) { + this.dueParallelGateway(passElements, flowElements, curFlowElement, variableMap); + } + } + + private void dueUserTaskElement(List passElements, Collection flowElements, + FlowElement curFlowElement, Map variableMap) { + passElements.add(curFlowElement); + List outgoingFlows = ((UserTask) curFlowElement).getOutgoingFlows(); + String targetRef = outgoingFlows.get(0).getTargetRef(); + if (outgoingFlows.size() > 1) { + // 找到表达式成立的sequenceFlow + SequenceFlow sequenceFlow = getSequenceFlow(variableMap, outgoingFlows); + targetRef = sequenceFlow.getTargetRef(); + } + // 根据ID找到FlowElement + FlowElement targetElement = getFlowElement(flowElements, targetRef); + this.getPassElementList(passElements, flowElements, targetElement, variableMap); + } + + private void dueExclusiveGateway(List passElements, Collection flowElements, FlowElement curFlowElement, Map variableMap) { + // 获取符合条件的sequenceFlow的目标FlowElement + List exclusiveGatewayOutgoingFlows = ((ExclusiveGateway) curFlowElement).getOutgoingFlows(); + flowElements.remove(curFlowElement); + // 找到表达式成立的sequenceFlow + SequenceFlow sequenceFlow = getSequenceFlow(variableMap, exclusiveGatewayOutgoingFlows); + // 根据ID找到FlowElement + FlowElement targetElement = getFlowElement(flowElements, sequenceFlow.getTargetRef()); + this.getPassElementList(passElements, flowElements, targetElement, variableMap); + } + + private void dueParallelGateway(List passElements, Collection flowElements, FlowElement curFlowElement, Map variableMap) { + FlowElement targetElement; + List parallelGatewayOutgoingFlows = ((ParallelGateway) curFlowElement).getOutgoingFlows(); + for (SequenceFlow sequenceFlow : parallelGatewayOutgoingFlows) { + targetElement = getFlowElement(flowElements, sequenceFlow.getTargetRef()); + this.getPassElementList(passElements, flowElements, targetElement, variableMap); + } + } + + private FlowElement getFlowElement(Collection flowElements, String targetRef) { + return flowElements.stream().filter(flowElement -> targetRef.equals(flowElement.getId())).findFirst().orElse(null); + } + + /** + * 4. 根据传入的变量,计算出表达式成立的那一条SequenceFlow + * + * @param variableMap + * @param outgoingFlows + * @return + */ + private SequenceFlow getSequenceFlow(Map variableMap, List outgoingFlows) { + Optional sequenceFlowOpt = outgoingFlows.stream().filter(item -> { + try { + return this.getElValue(item.getConditionExpression(), variableMap); + } catch (Exception e) { + log.error(e.getMessage(), e); + return false; + } + }).findFirst(); + return sequenceFlowOpt.orElse(outgoingFlows.get(0)); + } + + private boolean getElValue(String exp, Map variableMap) { + return managementService.executeCommand(new ExpressionCmd(runtimeService, processEngineConfiguration, null, exp, variableMap)); + } + + public ResultBean businessStartProcessInstanceById(BusinessVariables bv) { + ResultBean rb = ResultBean.fireFail(); + UpdateFlowFieldVo updateFlowFieldVo = new UpdateFlowFieldVo(); + String procDefId = bv.getModelId(); + String userSid = bv.getUserSid(); + String nextNodeUserSids = bv.getNextNodeUserSids(); + Map variables = bv.getFormVariables(); + Map variablesSeconds = bv.getFormVariables(); + //根据流程定义id查询 + ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery().processDefinitionId(procDefId) + .latestVersion().singleResult(); + if (Objects.nonNull(processDefinition) && processDefinition.isSuspended()) { + return rb.setMsg("流程已被挂起,请先激活流程"); + } + // 设置流程发起人Id到流程中 + ResultBean sysUserVoResultBean = sysUserFeign.fetchBySid(userSid); + SysUserVo sysUser = sysUserVoResultBean.getData(); + identityService.setAuthenticatedUserId(sysUser.getSid()); + variables.put(ProcessConstants.PROCESS_INITIATOR, userSid); + variables.put(ProcessConstants.USER_TYPE_ASSIGNEE, userSid); + ProcessInstance processInstance = runtimeService.startProcessInstanceById(procDefId, variables); + // 给第一步申请人节点设置任务执行人和意见 todo:第一个节点不设置为申请人节点有点问题? + Task task = taskService.createTaskQuery().processInstanceId(processInstance.getProcessInstanceId()).singleResult(); + if (Objects.nonNull(task)) { + taskService.addComment(task.getId(), processInstance.getProcessInstanceId(), FlowComment.START.getType(), + sysUser.getName() + "发起流程申请"); + taskService.setAssignee(task.getId(), userSid); + taskService.setVariablesLocal(task.getId(), variables); + taskService.complete(task.getId(), variables); + } + + //根据流程实例的id查询最新的待办环节 + ResultBean> latestTasksNew = flowTaskService.getLatestTasksNew(processInstance.getId()); + List data = latestTasksNew.getData(); + LatestTaskVo latestTaskVo = data.get(0); + String id_ = latestTaskVo.getId_(); + String task_def_key_ = latestTaskVo.getTask_def_key_(); + //查询下一环节是否有转办并添加评论 + nextNodeUserSids = change(nextNodeUserSids, processInstance.getProcessInstanceId()); + taskService.setAssignee(id_, nextNodeUserSids); + if (ProcDefEnum.DEFAUL_TADMIN_SID.getProDefId().equals(nextNodeUserSids)) { + bv.setModelId(procDefId); + bv.setInstanceId(task.getProcessInstanceId()); + bv.setTaskId(id_); + bv.setUserSid(nextNodeUserSids); + bv.setBusinessSid(bv.getBusinessSid()); + bv.setTaskDefKey(task_def_key_); + bv.setFormVariables(variables); + bv.setOrgSidPath(bv.getOrgSidPath()); + bv.setComment("系统自动跳过!"); + bv.setFormVariables(variablesSeconds); + bv.setNextNodeUserSids(""); + ResultBean updateFlowFieldVoResultBean = handleProsess(bv, false); + if (updateFlowFieldVoResultBean.getSuccess() && updateFlowFieldVoResultBean.getData() != null) { + UpdateFlowFieldVo vo = updateFlowFieldVoResultBean.getData(); + updateFlowFieldVo.setProcInsId(vo.getProcInsId()); + updateFlowFieldVo.setNodeState(vo.getNodeState()); + updateFlowFieldVo.setTaskId(vo.getTaskId()); + updateFlowFieldVo.setTaskDefKey(vo.getTaskDefKey()); + updateFlowFieldVo.setProcDefId(bv.getModelId()); + updateFlowFieldVo.setSid(bv.getBusinessSid()); + rb.success().setData(updateFlowFieldVo).setMsg("流程启动成功"); + } + } + if (bv.getUserSid().equals(nextNodeUserSids)) { + //如果申请人与下一环节审批人相同,则自动审批 + bv.setModelId(procDefId); + bv.setInstanceId(task.getProcessInstanceId()); + bv.setTaskId(id_); + bv.setUserSid(nextNodeUserSids); + bv.setBusinessSid(bv.getBusinessSid()); + bv.setTaskDefKey(task_def_key_); + bv.setFormVariables(variables); + bv.setOrgSidPath(bv.getOrgSidPath()); + bv.setFormVariables(variablesSeconds); + bv.setComment("因与申请人相同,系统自动处理,需以下一级审批人审批意见为准!"); + bv.setNextNodeUserSids(""); + ResultBean updateFlowFieldVoResultBean = handleProsess(bv, false); + if (updateFlowFieldVoResultBean.getSuccess() && updateFlowFieldVoResultBean.getData() != null) { + UpdateFlowFieldVo vo = updateFlowFieldVoResultBean.getData(); + updateFlowFieldVo.setProcInsId(vo.getProcInsId()); + updateFlowFieldVo.setNodeState(vo.getNodeState()); + updateFlowFieldVo.setTaskId(vo.getTaskId()); + updateFlowFieldVo.setTaskDefKey(vo.getTaskDefKey()); + updateFlowFieldVo.setProcDefId(bv.getModelId()); + updateFlowFieldVo.setSid(bv.getBusinessSid()); + rb.success().setData(updateFlowFieldVo).setMsg("流程启动成功"); + } + } + updateFlowFieldVo.setProcInsId(task.getProcessInstanceId()); + updateFlowFieldVo.setNodeState(latestTaskVo.getName_()); + updateFlowFieldVo.setTaskId(id_); + updateFlowFieldVo.setTaskDefKey(task_def_key_); + updateFlowFieldVo.setProcDefId(bv.getModelId()); + updateFlowFieldVo.setSid(bv.getBusinessSid()); + return rb.success().setData(updateFlowFieldVo).setMsg("流程启动成功"); + } + + /** + * 查询下一环节用户是否有转办用户,若有转办用户则添加转办评论 + * + * @param nextNodeUserSids 下一环节用户 + * @param instanceId 实例id + * @return + */ + public String change(String nextNodeUserSids, String instanceId) { + //查询下一环节是否有转办 + String firstSid = ""; + String firstName = ""; + //默认无转办 + boolean isChange = false; + if (StringUtils.isNotBlank(nextNodeUserSids)) { + List nextUserList = Arrays.asList(nextNodeUserSids.split(",")); + if (nextUserList.size() == 1) { + firstSid = nextUserList.get(0); + ResultBean userVoResultBean = sysUserFeign.fetchBySid(firstSid); + if (userVoResultBean.getData() != null) { + firstName = userVoResultBean.getData().getName(); + } + SysFlowableConfigQuery sysFlowableConfigQuery = new SysFlowableConfigQuery(); + sysFlowableConfigQuery.setUserSid(firstSid); + sysFlowableConfigQuery.setNowDate(new Date()); + ResultBean sysFlowableConfigVvoResultBean = sysFlowableConfigFeign.selectByUserSid(sysFlowableConfigQuery); + if (sysFlowableConfigVvoResultBean.getData() != null) { + if (StringUtils.isNotBlank(sysFlowableConfigVvoResultBean.getData().getChangeUserSid())) { + nextNodeUserSids = sysFlowableConfigVvoResultBean.getData().getChangeUserSid(); + isChange = true; + } + } + } + } + if (isChange) {//添加评论 + ResultBean userVoResultBean = sysUserFeign.fetchBySid(nextNodeUserSids); + ProcessCommentDto processCommentDto = new ProcessCommentDto(); + processCommentDto.setReviewerSid(firstSid); + if (userVoResultBean.getData() != null) { + String changeName = userVoResultBean.getData().getName(); + processCommentDto.setReviewer(firstName); + processCommentDto.setContent("交" + changeName + "转办"); + } + processCommentDto.setTime(new Date()); + processCommentDto.setProcessId(instanceId); + processCommentService.saveOrUpdateDto(processCommentDto); + } + return nextNodeUserSids; + } + + public ResultBean handleProsess(BusinessVariables bv, boolean b) { + ResultBean rb = ResultBean.fireFail(); + UpdateFlowFieldVo vo = new UpdateFlowFieldVo(); + //获取表单中的参数 + Map formVariables = bv.getFormVariables(); + formVariables = formVariables == null ? new HashMap<>() : formVariables; + formVariables.put("businessSid", bv.getBusinessSid()); + String nextUserSid = bv.getNextNodeUserSids(); + String taskId = bv.getTaskId(); + String userSid = bv.getUserSid(); + String instanceId = bv.getInstanceId(); + String comment = bv.getComment(); + String nodeState = ""; + String taskDefKey = ""; + String orgPath = bv.getOrgSidPath(); + //设置下一环节审批人是否自动审批通过,默认否 + boolean contains = false; + //设置是否是管理员自动审批,默认否 + boolean adminContains = false; + if (StringUtils.isBlank(nextUserSid)) { + ResultBean stringResultBean = getNextNodeUserSidsOfSubmit(bv); + if (!stringResultBean.getSuccess()) { + //下一环节用户为空的情况 + nextUserSid = ProcDefEnum.DEFAUL_TADMIN_SID.getProDefId(); + adminContains = true; + } else { + nextUserSid = stringResultBean.getData(); + } + } else { + //若下一环节用户与系统管理员一致,则自动审批 + if (ProcDefEnum.DEFAUL_TADMIN_SID.getProDefId().equals(nextUserSid)) { + adminContains = true; + } + } + //查询任务id为taskId的任务是否存在 + Task task = taskService.createTaskQuery().taskId(taskId).singleResult(); + if (Objects.isNull(task)) { + return rb.setMsg("任务不存在"); + } + String assignee = task.getAssignee(); + if (b && (StringUtils.isNotBlank(assignee) && assignee.indexOf(userSid) < 0)) { + return rb.setMsg("当前用户不是环节的待办人,不能进行办理操作!"); + } + + if (DelegationState.PENDING.equals(task.getDelegationState())) { + //加签 + taskService.addComment(taskId, instanceId, + FlowComment.DELEGATE.getType(), comment); + taskService.resolveTask(taskId, formVariables); + } else { + //当前环节办理通过,且将下一环节用户放入流程中 + taskService.addComment(taskId, instanceId, FlowComment.NORMAL.getType(), comment); + log.error("taskid:{},userSid:{}", taskId, userSid); + log.error("formVariables:{}", JSON.toJSONString(formVariables)); + taskService.setAssignee(taskId, userSid); + taskService.complete(taskId, formVariables);//当前用户办理通过 + //根据流程实例的id取最新的待办环节,给环节设置上用户sid + ResultBean> ll = flowTaskService.getLatestTasksNew(instanceId); + if (ll.getData().size() > 0) { + LatestTaskVo latestTaskVo = ll.getData().get(0); + String id_ = latestTaskVo.getId_(); + //查询下一环节用户是否有转办人 + nextUserSid = change(nextUserSid, bv.getInstanceId()); + taskService.setAssignee(id_, nextUserSid);//将下一环节用户放入流程中 + vo.setTaskId(id_); + //在act_ru_variable表中增加环节上的业务参数的变量 + taskService.setVariablesLocal(id_, formVariables); + nodeState = latestTaskVo.getName_(); + taskDefKey = latestTaskVo.getTask_def_key_(); + } else { + nodeState = FlowComment.SETTLE.getRemark(); + taskDefKey = "Event_end"; + vo.setNodeState(FlowComment.SETTLE.getRemark()); + } + } + //设置管理员是否自动审批的字段是否是是。//若下一环节用户与系统管理员一致,则自动审批 + if (adminContains) { + bv.setUserSid(nextUserSid); + bv.setTaskId(vo.getTaskId()); + bv.setTaskDefKey(taskDefKey); + bv.setComment("系统自动跳过"); + bv.setNextNodeUserSids(""); + return handleProsess(bv, false); + } + //获取该流程所有要走的环节节点 + List flowElements = calApprovePath(bv.getModelId(), + bv.getFormVariables()); + for (int i = 0; i < flowElements.size(); i++) { + FlowElement flowElement = flowElements.get(i); + String id = flowElement.getId(); + if (taskDefKey.equals(id) && i + 1 < flowElements.size()) { + //获取下下一环节 + FlowElement flowElement1 = flowElements.get(i + 1); + List sysUserVoLists2 = new ArrayList<>(); + if (i + 2 < flowElements.size()) { + //获取下下下一环节用户 + FlowElement flowElement2 = flowElements.get(i + 2); + if (flowElement2 instanceof UserTask) { + UserTask userTask = (UserTask) flowElement2; + List candidateGroups = userTask.getCandidateGroups(); + UserssQuery userssQuery = new UserssQuery(); + userssQuery.setCandidateGroups(candidateGroups); + userssQuery.setOrgSidPath(orgPath); + sysUserVoLists2 = sysUserFeign.getUsersByRoles(userssQuery).getData(); + if (sysUserVoLists2 == null) { + sysUserVoLists2 = new ArrayList<>(); + } + } + } + if (flowElement1 instanceof UserTask) { + UserTask userTask = (UserTask) flowElement1; + List candidateGroups = userTask.getCandidateGroups(); + List sysUserVoLists = new ArrayList<>(); + UserssQuery userssQuery = new UserssQuery(); + userssQuery.setCandidateGroups(candidateGroups); + userssQuery.setOrgSidPath(orgPath); + sysUserVoLists = sysUserFeign.getUsersByRoles(userssQuery).getData(); + if (sysUserVoLists == null) { + sysUserVoLists = new ArrayList<>(); + } + //当前环节运营部总经理 刘丽艳 点击同意 下一环节 事业部副总经理 (nextUserSid) 和事业部总经理(sysUserVoLists.get(0).getSid()) + //判断查询回来的用户的集合size是1 并且用户的sid和下一环节的用户的sid相同。 + if (sysUserVoLists.size() == 1 && sysUserVoLists.get(0).getSid().equals(nextUserSid)) { + contains = true; + break; + } + //如果下下一环节无用户,下下下一环节用户与下一环节用户相同且只有一个,则下一环节用户自动审批。 + if (sysUserVoLists.size() == 0 && sysUserVoLists2.size() == 1 && sysUserVoLists2.get(0).getSid().equals(nextUserSid)) { + contains = true; + break; + } + } + } + if (contains) { + break; + } + } + if (contains) { + bv.setUserSid(nextUserSid); + bv.setTaskId(vo.getTaskId()); + bv.setTaskDefKey(taskDefKey); + bv.setComment("因与下一级审批人相同,系统自动处理,需以下一级审批人审批意见为准!"); + return handleProsess(bv, false); + } + vo.setProcInsId(instanceId); + vo.setProcDefId(bv.getModelId()); + vo.setNodeState(nodeState); + vo.setTaskDefKey(taskDefKey); + vo.setSid(bv.getBusinessSid()); + return rb.success().setData(vo); + } + + /** + * 获取下一环节用户 + * + * @param bv + * @return + */ + public ResultBean getNextNodeUserSidsOfSubmit(BusinessVariables bv) { + ResultBean rb = ResultBean.fireFail(); + String orgPath = bv.getOrgSidPath(); + String taskDefKey = bv.getTaskDefKey(); + //根据业务参数取流程流转的环节 信息 + List> list = (List>) getProcessCirculationNodesByMap(bv).getData(); + Map task_map = new HashMap<>(); + boolean endTask = true; + for (int i = 0; i < list.size(); i++) { + String id = list.get(i).get("id").toString(); + if (id.equals(taskDefKey) && i + 1 < list.size()) { + task_map = list.get(i + 1); + endTask = false; + } + } + if (endTask) { + task_map.put("name", "结束"); + return rb.success(); + } else { + Object o = task_map.get("candidateGroups"); + JSONArray jsonArray = JSONArray.parseArray(JSON.toJSONString(o)); + String roleSid = jsonArray.get(0).toString(); + //根据组织架构、角色两个参数取相关符合条件的用户信息 + UserQuery userQuery = new UserQuery(); + userQuery.setRoleSid(roleSid); + userQuery.setOrgSidPath(orgPath); + String nextNodeUserSids_ = ""; + List sysUserVos = sysUserFeign.getUserByRole(userQuery).getData(); + if (sysUserVos == null || sysUserVos.size() < 1) { + return rb; + } else { + StringBuilder nextNodeUserSids = new StringBuilder(); + for (SysUserVo su : sysUserVos) { + nextNodeUserSids.append(su.getSid()).append(","); + } + //符合条件的用户的sid,拼接的字符串 + nextNodeUserSids_ = nextNodeUserSids.toString(); + nextNodeUserSids_ = nextNodeUserSids_.substring(0, nextNodeUserSids_.length() - 1); + } + return rb.success().setData(nextNodeUserSids_); + } + + + } +} From bf9c8ed02b520f52152f83a8e9ab1160422de7bd Mon Sep 17 00:00:00 2001 From: dimengzhe Date: Fri, 21 Jul 2023 14:12:54 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=E8=AE=BE=E7=BD=AE=E8=87=AA=E5=8A=A8?= =?UTF-8?q?=E8=BD=AC=E5=8A=9E=E6=B7=BB=E5=8A=A0=E6=8A=84=E9=80=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../anrui/flowable/biz/flow/FlowableRest.java | 7 + .../anrui/flowable/biz/flow2/FlowRest.java | 119 +-------------- .../anrui/flowable/biz/flow2/FlowService.java | 141 +++++++++++++++++- .../processcomment/ProcessCommentMapper.java | 2 + .../processcomment/ProcessCommentMapper.xml | 4 + .../processcomment/ProcessCommentService.java | 4 + 6 files changed, 153 insertions(+), 124 deletions(-) diff --git a/anrui-flowable/anrui-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flow/FlowableRest.java b/anrui-flowable/anrui-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flow/FlowableRest.java index 5eb18271a3..4286cafc9f 100644 --- a/anrui-flowable/anrui-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flow/FlowableRest.java +++ b/anrui-flowable/anrui-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flow/FlowableRest.java @@ -205,6 +205,13 @@ public class FlowableRest implements FlowableFeign { if (processVariables.containsKey("sendRecommendSid")) {//增加的其他的抄送人 userSids.append(processVariables.get("sendRecommendSid").toString()).append(","); } + //查询是否有设置转办的,抄送给设置转办人员 + List zbUserSids = processCommentService.selectByIdAndComment("转办",bv.getInstanceId()); + zbUserSids.removeAll(Collections.singleton(null)); + if(!zbUserSids.isEmpty()){ + String zbUser = String.join(",",zbUserSids); + userSids.append(zbUser).append(","); + } userSids.deleteCharAt(userSids.length() - 1); mfq.setUserSids(userSids.toString()); mfq.setOrgPath(createrOrgPath); diff --git a/anrui-flowable/anrui-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flow2/FlowRest.java b/anrui-flowable/anrui-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flow2/FlowRest.java index 0df8db0cf7..255bfa6c0a 100644 --- a/anrui-flowable/anrui-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flow2/FlowRest.java +++ b/anrui-flowable/anrui-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flow2/FlowRest.java @@ -44,19 +44,9 @@ public class FlowRest implements FlowFeign { @Autowired private FlowService flowService; - @Autowired - private SysFlowccFeign sysFlowccFeign; - @Autowired - private SysUserFeign sysUserFeign; @Autowired - protected HistoryService historyService; - - @Autowired - private ProcessService processService; - - @Autowired - private MessageFeign messageFeign; + private SysUserFeign sysUserFeign; @Override public ResultBean startProcess(BusinessVariables bv) { @@ -99,7 +89,7 @@ public class FlowRest implements FlowFeign { UpdateFlowFieldVo ufVo = updateFlowFieldVoResultBean.getData(); ufVo.setTaskId(bv.getTaskId()); map.put("uff", ufVo); - cc(map, bv.getTaskDefKey()); + flowService.cc(map, bv.getTaskDefKey()); }); } catch (Exception e) { e.printStackTrace(); @@ -110,110 +100,5 @@ public class FlowRest implements FlowFeign { return updateFlowFieldVoResultBean; } - /** - * 流程抄送的功能 - * - * @param map - * @return - */ - public ResultBean cc(Map map, String taskDefKey) { - ResultBean rb = ResultBean.fireFail(); - log.info("FlowableRest-cc:{}", JSONObject.toJSONString(map)); - Object bv1 = map.get("bv"); - BusinessVariables bv = new BusinessVariables(); - BeanUtil.copyProperties(bv1, bv); - Object uff1 = map.get("uff"); - UpdateFlowFieldVo uff = new UpdateFlowFieldVo(); - BeanUtil.copyProperties(uff1, uff); - uff.setTaskDefKey(taskDefKey); - //流程定义的id - String modelId = bv.getModelId(); - //将modelId根据冒号:分成三部分,取第一部分作为key - List stringList = Arrays.asList(modelId.split(":")); - modelId = stringList.get(0); - //抄送的角色的sid - ResultBean roleSidByModelId = sysFlowccFeign.getRoleSidByModelId(modelId); - //组织机构sid - String orgSidPath = bv.getOrgSidPath(); - if (roleSidByModelId.getData() == null) { - log.info("抄送失败,没有配置对应的角色!"); - return rb.setMsg("抄送失败,没有配置对应的角色!"); - } - SysFlowccVo data = roleSidByModelId.getData(); - if (StringUtils.isBlank(data.getRoleSid())) { - log.info("抄送失败,没有配置对应的角色!"); - return rb.setMsg("抄送失败,没有配置对应的角色!"); - } - List list = Arrays.asList(data.getRoleSid().split(",")); - UserByRolesAndOrgQuery userQuery = new UserByRolesAndOrgQuery(); - userQuery.setRoleSids(list); - userQuery.setOrgSidPath(orgSidPath); - List sysUserVos = sysUserFeign.getUserByRoles(userQuery).getData(); - if (sysUserVos == null || sysUserVos.size() < 1) { - log.info("抄送失败,没有用户!"); - return rb.setMsg("抄送失败,没有用户!"); - } - StringBuilder userName = new StringBuilder(); - StringBuilder userSids = new StringBuilder(); - sysUserVos.forEach(f -> { - userName.append(f.getName()).append(","); - userSids.append(f.getSid()).append(","); - }); - - //抄送的业务逻辑 - MessageFlowableQuery mfq = new MessageFlowableQuery(); - MessageFlowVo messageFlowVo = new MessageFlowVo(); - BeanUtil.copyProperties(uff, messageFlowVo); - mfq.setUfVo(messageFlowVo); - //移动端的参数 - HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery() - .includeProcessVariables().taskId(bv.getTaskId()).singleResult(); - if (historicTaskInstance == null) { - log.info("抄送失败:没有获取到业务参数!"); - return rb.setMsg("抄送失败!"); - } - Map processVariables = historicTaskInstance.getProcessVariables(); - String createrOrgPath = (String) processVariables.get("createrOrgPath"); - if (historicTaskInstance == null) { - log.info("抄送失败:没有获取到业务参数!"); - return rb.setMsg("抄送失败!"); - } - Map app = new HashMap<>(); - if (processVariables.get("app") != null) { - app = (Map) processVariables.get("app"); - } - log.info("抄送方法-historicTaskInstance:{}", JSONObject.toJSONString(historicTaskInstance)); - mfq.setAppMap(app); - mfq.setBusinessSid(bv.getBusinessSid()); - - mfq.setMsgContent("系统抄送的流程审批,请查看"); -// act_re_procdef - Map process = processService.getProcessDefByDefId(historicTaskInstance.getProcessDefinitionId()); - log.info("抄送成功-process:{}", process); - if (process == null) { - log.info("抄送失败,流程定义不存在!"); - return rb.setMsg("抄送失败,流程定义不存在!"); - } - mfq.setModuleName(process.get("NAME_")); - if (processVariables.containsKey("orderNames")) { - mfq.setMsgTitle(processVariables.get("orderNames").toString()); - } else { - mfq.setMsgTitle(process.get("NAME_")); - } - if (processVariables.containsKey("sendRecommendSid")) {//增加的其他的抄送人 - userSids.append(processVariables.get("sendRecommendSid").toString()).append(","); - } - userSids.deleteCharAt(userSids.length() - 1); - mfq.setUserSids(userSids.toString()); - mfq.setOrgPath(createrOrgPath); - ResultBean resultBean = messageFeign.pushMessageCC(mfq); - log.info("抄送成功:{}", userName.toString()); - log.info("抄送成功-resultBean:{}", resultBean); - if (!resultBean.getSuccess()) { - log.info("抄送失败,同送消息异常!:{}", JSONObject.toJSONString(resultBean)); - return rb.setMsg("抄送失败,同送消息异常!"); - } - return rb.success().setMsg("抄送" + userName.toString() + "成功!"); - } } diff --git a/anrui-flowable/anrui-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flow2/FlowService.java b/anrui-flowable/anrui-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flow2/FlowService.java index 8349c2bee1..2ef8b208b8 100644 --- a/anrui-flowable/anrui-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flow2/FlowService.java +++ b/anrui-flowable/anrui-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/flow2/FlowService.java @@ -1,5 +1,6 @@ package com.yxt.anrui.flowable.biz.flow2; +import cn.hutool.core.bean.BeanUtil; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONArray; import com.alibaba.fastjson.JSONObject; @@ -12,16 +13,19 @@ import com.yxt.anrui.flowable.api.processcomment.ProcessCommentDto; import com.yxt.anrui.flowable.api.utils.ProcDefEnum; import com.yxt.anrui.flowable.biz.flowtask.FlowTaskService; import com.yxt.anrui.flowable.biz.process.ExpressionCmd; +import com.yxt.anrui.flowable.biz.process.ProcessService; import com.yxt.anrui.flowable.biz.processcomment.ProcessCommentService; import com.yxt.anrui.flowable.common.ProcessConstants; +import com.yxt.anrui.flowable.feign.MessageFeign; +import com.yxt.anrui.flowable.feign.form.MessageFlowVo; +import com.yxt.anrui.flowable.feign.form.MessageFlowableQuery; import com.yxt.anrui.flowable.sqloperationsymbol.BusinessVariables; import com.yxt.anrui.portal.api.sysflowableconfig.SysFlowableConfigFeign; import com.yxt.anrui.portal.api.sysflowableconfig.SysFlowableConfigQuery; import com.yxt.anrui.portal.api.sysflowableconfig.SysFlowableConfigVvo; -import com.yxt.anrui.portal.api.sysuser.SysUserFeign; -import com.yxt.anrui.portal.api.sysuser.SysUserVo; -import com.yxt.anrui.portal.api.sysuser.UserQuery; -import com.yxt.anrui.portal.api.sysuser.UserssQuery; +import com.yxt.anrui.portal.api.sysflowcc.SysFlowccFeign; +import com.yxt.anrui.portal.api.sysflowcc.SysFlowccVo; +import com.yxt.anrui.portal.api.sysuser.*; import com.yxt.common.base.service.MybatisBaseService; import com.yxt.common.base.utils.StringUtils; import com.yxt.common.core.result.ResultBean; @@ -33,6 +37,7 @@ import org.flowable.engine.repository.ProcessDefinition; import org.flowable.engine.runtime.ProcessInstance; import org.flowable.task.api.DelegationState; import org.flowable.task.api.Task; +import org.flowable.task.api.history.HistoricTaskInstance; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -70,6 +75,17 @@ public class FlowService extends MybatisBaseService { @Autowired private ProcessCommentService processCommentService; + @Autowired + protected HistoryService historyService; + + @Autowired + private ProcessService processService; + + @Autowired + private MessageFeign messageFeign; + @Autowired + private SysFlowccFeign sysFlowccFeign; + public ResultBean getNextNodeUser(BusinessVariables bv) { ResultBean rb = ResultBean.fireFail(); //根据业务参数取流程流转的环节 信息 @@ -121,7 +137,6 @@ public class FlowService extends MybatisBaseService { map.put("candidateGroups", candidateGroups); list.add(map); } -// List> list= JSON.parseObject(JSON.toJSONString(flowElements), new TypeReference>>() {}); return rb.setData(list); } @@ -301,7 +316,7 @@ public class FlowService extends MybatisBaseService { updateFlowFieldVo.setTaskDefKey(vo.getTaskDefKey()); updateFlowFieldVo.setProcDefId(bv.getModelId()); updateFlowFieldVo.setSid(bv.getBusinessSid()); - rb.success().setData(updateFlowFieldVo).setMsg("流程启动成功"); + return rb.success().setData(updateFlowFieldVo).setMsg("流程启动成功"); } } if (bv.getUserSid().equals(nextNodeUserSids)) { @@ -326,7 +341,7 @@ public class FlowService extends MybatisBaseService { updateFlowFieldVo.setTaskDefKey(vo.getTaskDefKey()); updateFlowFieldVo.setProcDefId(bv.getModelId()); updateFlowFieldVo.setSid(bv.getBusinessSid()); - rb.success().setData(updateFlowFieldVo).setMsg("流程启动成功"); + return rb.success().setData(updateFlowFieldVo).setMsg("流程启动成功"); } } updateFlowFieldVo.setProcInsId(task.getProcessInstanceId()); @@ -586,7 +601,119 @@ public class FlowService extends MybatisBaseService { } return rb.success().setData(nextNodeUserSids_); } + } + /** + * 流程抄送的功能 + * + * @param map + * @return + */ + public ResultBean cc(Map map, String taskDefKey) { + ResultBean rb = ResultBean.fireFail(); + log.info("FlowableRest-cc:{}", JSONObject.toJSONString(map)); + Object bv1 = map.get("bv"); + BusinessVariables bv = new BusinessVariables(); + BeanUtil.copyProperties(bv1, bv); + Object uff1 = map.get("uff"); + UpdateFlowFieldVo uff = new UpdateFlowFieldVo(); + BeanUtil.copyProperties(uff1, uff); + uff.setTaskDefKey(taskDefKey); + //流程定义的id + String modelId = bv.getModelId(); + //将modelId根据冒号:分成三部分,取第一部分作为key + List stringList = Arrays.asList(modelId.split(":")); + modelId = stringList.get(0); + //抄送的角色的sid + ResultBean roleSidByModelId = sysFlowccFeign.getRoleSidByModelId(modelId); + //组织机构sid + String orgSidPath = bv.getOrgSidPath(); + if (roleSidByModelId.getData() == null) { + log.info("抄送失败,没有配置对应的角色!"); + return rb.setMsg("抄送失败,没有配置对应的角色!"); + } + SysFlowccVo data = roleSidByModelId.getData(); + if (StringUtils.isBlank(data.getRoleSid())) { + log.info("抄送失败,没有配置对应的角色!"); + return rb.setMsg("抄送失败,没有配置对应的角色!"); + } + List list = Arrays.asList(data.getRoleSid().split(",")); + UserByRolesAndOrgQuery userQuery = new UserByRolesAndOrgQuery(); + userQuery.setRoleSids(list); + userQuery.setOrgSidPath(orgSidPath); + List sysUserVos = sysUserFeign.getUserByRoles(userQuery).getData(); + if (sysUserVos == null || sysUserVos.size() < 1) { + log.info("抄送失败,没有用户!"); + return rb.setMsg("抄送失败,没有用户!"); + } + StringBuilder userName = new StringBuilder(); + StringBuilder userSids = new StringBuilder(); + sysUserVos.forEach(f -> { + userName.append(f.getName()).append(","); + userSids.append(f.getSid()).append(","); + }); + + //抄送的业务逻辑 + MessageFlowableQuery mfq = new MessageFlowableQuery(); + MessageFlowVo messageFlowVo = new MessageFlowVo(); + BeanUtil.copyProperties(uff, messageFlowVo); + mfq.setUfVo(messageFlowVo); + //移动端的参数 + HistoricTaskInstance historicTaskInstance = historyService.createHistoricTaskInstanceQuery() + .includeProcessVariables().taskId(bv.getTaskId()).singleResult(); + if (historicTaskInstance == null) { + log.info("抄送失败:没有获取到业务参数!"); + return rb.setMsg("抄送失败!"); + } + Map processVariables = historicTaskInstance.getProcessVariables(); + String createrOrgPath = (String) processVariables.get("createrOrgPath"); + if (historicTaskInstance == null) { + log.info("抄送失败:没有获取到业务参数!"); + return rb.setMsg("抄送失败!"); + } + Map app = new HashMap<>(); + if (processVariables.get("app") != null) { + app = (Map) processVariables.get("app"); + } + log.info("抄送方法-historicTaskInstance:{}", JSONObject.toJSONString(historicTaskInstance)); + mfq.setAppMap(app); + mfq.setBusinessSid(bv.getBusinessSid()); + + mfq.setMsgContent("系统抄送的流程审批,请查看"); +// act_re_procdef + Map process = processService.getProcessDefByDefId(historicTaskInstance.getProcessDefinitionId()); + log.info("抄送成功-process:{}", process); + if (process == null) { + log.info("抄送失败,流程定义不存在!"); + return rb.setMsg("抄送失败,流程定义不存在!"); + } + mfq.setModuleName(process.get("NAME_")); + if (processVariables.containsKey("orderNames")) { + mfq.setMsgTitle(processVariables.get("orderNames").toString()); + } else { + mfq.setMsgTitle(process.get("NAME_")); + } + if (processVariables.containsKey("sendRecommendSid")) {//增加的其他的抄送人 + userSids.append(processVariables.get("sendRecommendSid").toString()).append(","); + } + //查询是否有设置转办的,抄送给设置转办人员 + List zbUserSids = processCommentService.selectByIdAndComment("转办",bv.getInstanceId()); + zbUserSids.removeAll(Collections.singleton(null)); + if(!zbUserSids.isEmpty()){ + String zbUser = String.join(",",zbUserSids); + userSids.append(zbUser).append(","); + } + userSids.deleteCharAt(userSids.length() - 1); + mfq.setUserSids(userSids.toString()); + mfq.setOrgPath(createrOrgPath); + ResultBean resultBean = messageFeign.pushMessageCC(mfq); + log.info("抄送成功:{}", userName.toString()); + log.info("抄送成功-resultBean:{}", resultBean); + if (!resultBean.getSuccess()) { + log.info("抄送失败,同送消息异常!:{}", JSONObject.toJSONString(resultBean)); + return rb.setMsg("抄送失败,同送消息异常!"); + } + return rb.success().setMsg("抄送" + userName.toString() + "成功!"); } } diff --git a/anrui-flowable/anrui-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/processcomment/ProcessCommentMapper.java b/anrui-flowable/anrui-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/processcomment/ProcessCommentMapper.java index 2974556ee8..dcc3730a67 100644 --- a/anrui-flowable/anrui-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/processcomment/ProcessCommentMapper.java +++ b/anrui-flowable/anrui-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/processcomment/ProcessCommentMapper.java @@ -69,4 +69,6 @@ public interface ProcessCommentMapper extends BaseMapper { ProcessComment fetchBySid(@Param("sid")String sid); void insertByDto(ProcessCommentDto dto); + + List selectByIdAndComment(@Param("comment") String comment, @Param("instanceId") String instanceId); } \ No newline at end of file diff --git a/anrui-flowable/anrui-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/processcomment/ProcessCommentMapper.xml b/anrui-flowable/anrui-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/processcomment/ProcessCommentMapper.xml index 3551c99e56..b44df399cb 100644 --- a/anrui-flowable/anrui-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/processcomment/ProcessCommentMapper.xml +++ b/anrui-flowable/anrui-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/processcomment/ProcessCommentMapper.xml @@ -17,4 +17,8 @@ insert into `process_comment` ( `sid`, `reviewer`, `reviewerSid`, `time`, `content`, `processId`, `processInstSid`,processFile) values(#{sid},#{reviewer},#{reviewerSid},#{time},#{content},#{processId},#{processInstSid},#{processFile}); + + \ No newline at end of file diff --git a/anrui-flowable/anrui-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/processcomment/ProcessCommentService.java b/anrui-flowable/anrui-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/processcomment/ProcessCommentService.java index 05da790cc9..4095efe52f 100644 --- a/anrui-flowable/anrui-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/processcomment/ProcessCommentService.java +++ b/anrui-flowable/anrui-flowable-biz/src/main/java/com/yxt/anrui/flowable/biz/processcomment/ProcessCommentService.java @@ -135,4 +135,8 @@ public class ProcessCommentService extends MybatisBaseService selectByIdAndComment(String comment, String instanceId) { + return baseMapper.selectByIdAndComment(comment, instanceId); + } } \ No newline at end of file