苍穹工作流那些事 之 自由流程
企业内部在处理流程审批业务时,可能会遇到以下应用场景:无法预置工作流,在进行审批时才根据业务需要确定流程审批节点、审批人。
为此,苍穹工作流提供了对自由流程的支持。构建好的自由流程,处理过程被完整记录,流程实例纳入监控管理体系,既保障了灵活性,又确保了处理过程的严谨性、可追溯性。
本期,小编就带大家详细了解苍穹工作流的自由流程功能。
1 业务场景
1、在发起流程时,由流程发起人确定当前业务单据要流转的审批流信息,包括有哪些审批节点和审批人。比如协同办公流程中,会出现发起人确定后续公文审批环节的情况。
2、在流程审批时,由审批人确认当前流程后续要流转的审批流信息,包括有哪些审批节点和审批人。
比如不同角色员工离职办理流程中,除一些通用处理节点,如直接上级审批、薪酬计算、离职证明等外,其他关键审批办理环节是不同的。一般由HR专员审批流程时,依据其职位、职级、部门、岗位类型等手动进行选择。
2 解决方案
苍穹工作流提供了自由流程接口和样例代码,支持通过调用接口构建流程,通过项目化交付,最大程度满足用户对流程的自由审批需要,丰富了苍穹工作流的应用场景。
3 功能实现
那自由流程功能是如何实现的呢?小编这就带大家开启探索之旅~
步骤一:在流程发起时,构建并启动自由流。相关代码示例如下:
private WFProcess createAndStartProcess() { String entityNumber = this.getModel().getDataEntityType().getName(); QFilter filter = new QFilter(NUMBER, QCP.equals, entityNumber); DynamicObject billInfo = BusinessDataServiceHelper.loadSingle(BOS_FORMMETA, QUERY_FIELD, new QFilter[]{filter}); //创建流程 WFProcess wfProcess = initProcess(billInfo); //人工节点,如果不传人工节点,默认会创建一个 WFUserTask wfUserTask = initWFUserTask(wfProcess); wfProcess.addNextNode(wfUserTask); //审批节点 WFAuditTask wfAuditTask = initWFAuditTask(wfProcess,wfUserTask.getId()); wfUserTask.addNextNode(wfAuditTask); //自动节点 WFAutoTask wfAutoTask = initWFAutoTask(wfProcess); wfAuditTask.addNextNode(wfAutoTask); //会审节点 WFJointAuditTask wfJointTask = initWFJointAuditTask(wfProcess,wfUserTask.getId(),wfAuditTask.getId()); wfAutoTask.addNextNode(wfJointTask); Mapvariables = new HashMap<>(); String businessKey = this.getModel().getDataEntity().getString("id"); String operation = "submit"; WorkflowServiceHelper.createProcessAndStart(businessKey , operation , entityNumber, variables, wfProcess); return wfProcess; }
其中,流程的创建如下:
private WFProcess initProcess(DynamicObject billInfo) { WFProcess wfProcess = new WFProcess(); wfProcess.setEntraBill(billInfo.getString(NUMBER)); wfProcess.setEntraBillId(billInfo.getString("id")); wfProcess.setEntraBillName(new LocaleString(billInfo.getLocaleString("name").getLocaleValue())); //流程插件 ListexecutionListeners = initExecutionListeners(); wfProcess.setExecutionListeners(executionListeners); //单据例外 ListbillExceptionOp = initBillexception(); wfProcess.setBillExceptionOp(billExceptionOp); //扩展实现其他属性:比如业务申请人和审批人相同时自动审批 MapextProps = new HashMap<>(); extProps.put("autoAuditWhenSamePerson", true); wfProcess.setExtProps(extProps); return wfProcess; }
人工节点的创建如下:
private WFUserTask initWFUserTask(WFProcess wfProcess) { WFUserTask wfUserTask = new WFUserTask(wfProcess); wfUserTask.setAllowCoordinate(true); wfUserTask.setAllowTransfer(true); WFParticipantModel participantModel = new WFParticipantModel(); participantModel.getParticipant().add(getParticipant1()); wfUserTask.setParticipant(participantModel); LocaleString name = new LocaleString(); name.put(Lang.zh_CN.name(), ResManager.loadKDString("自由流人工节点", "FreeFlowPlugin_19", WF_UNITTEST)); name.put(Lang.zh_TW.name(), ResManager.loadKDString("自由流人工节点", "FreeFlowPlugin_19", WF_UNITTEST)); name.put(Lang.en_US.name(), "freeflowUserTask"); wfUserTask.setName(name); ListdecisionOptions = initWFUserTaskDecisionOptions(); wfUserTask.setDecisionOptions(decisionOptions); return wfUserTask; }
审批节点的创建如下:
private WFAuditTask initWFAuditTask(WFProcess wfProcess, String id) { WFAuditTask wfAuditTask = new WFAuditTask(wfProcess); LocaleString name = new LocaleString(); name.put(Lang.zh_CN.name(), ResManager.loadKDString("自由流审批节点", "FreeFlowPlugin_13", WF_UNITTEST)); name.put(Lang.zh_TW.name(), ResManager.loadKDString("自由流审批节点", "FreeFlowPlugin_13", WF_UNITTEST)); name.put(Lang.en_US.name(), "freeflowAuditTask"); wfAuditTask.setName(name); //协办 wfAuditTask.setAllowCoordinate(true); //转交 wfAuditTask.setAllowTransfer(true); //加签 wfAuditTask.setCountersigned(true); //参与人 WFParticipantModel participantModel = new WFParticipantModel(); participantModel.getParticipant().add(getParticipant1()); participantModel.getParticipant().add(getParticipant2()); //participantModel.getParticipant().add(getParticipant3()); //participantModel.getParticipant().add(getParticipant4()); wfAuditTask.setParticipant(participantModel); //决策项 ListrejectNodeIds = new ArrayList<>(); if(WfUtils.isNotEmpty(id)){ rejectNodeIds.add(id); } ListdecisionOptions = initWFDecisionOptions(rejectNodeIds); wfAuditTask.setDecisionOptions(decisionOptions); //单据设置 WFBillSetting billSetting = new WFBillSetting(); billSetting.setFormKey(getView().getFormShowParameter().getFormId()); billSetting.setMobilFormKey("anquan$"); wfAuditTask.setBillSetting(billSetting); //自动审批 WFAutoAudit wfAutoAudit = getAutoAudit(wfAuditTask.getId()); wfAuditTask.setAutoAudit(wfAutoAudit); //自动跳过 WFConditionalRule skipCondition = initSkipCondition(wfAuditTask.getId()); wfAuditTask.setSkipCondition(skipCondition); //扩展实现其他属性:比如扩展业务按钮 MapextProps = initBtnModel(); wfAuditTask.setExtProps(extProps); return wfAuditTask; }
会审节点的创建如下:
private WFJointAuditTask initWFJointAuditTask(WFProcess wfProcess,String id1,String id2) { WFJointAuditTask wfJointTask = new WFJointAuditTask(wfProcess); LocaleString name = new LocaleString(); name.put(Lang.zh_CN.name(), ResManager.loadKDString("自由流会审节点", "FreeFlowPlugin_10", WF_UNITTEST)); name.put(Lang.zh_TW.name(), ResManager.loadKDString("自由流会审节点", "FreeFlowPlugin_10", WF_UNITTEST)); name.put(Lang.en_US.name(), "freeflowWFJointAuditTask"); wfJointTask.setName(name); //协办 wfJointTask.setAllowCoordinate(true); //转交 wfJointTask.setAllowTransfer(true); //加签 wfJointTask.setCountersigned(true); //参与人 WFParticipantModel participantModel = new WFParticipantModel(); participantModel.getParticipant().add(getParticipant1()); participantModel.getParticipant().add(getParticipant2()); participantModel.getParticipant().add(getParticipant3()); participantModel.getParticipant().add(getParticipant4()); wfJointTask.setParticipant(participantModel); //决策项 ListrejectNodeNumbers = new ArrayList<>(); if(WfUtils.isNotEmpty(id1)){ rejectNodeNumbers.add(id1); } if(WfUtils.isNotEmpty(id2)){ rejectNodeNumbers.add(id2); } ListdecisionOptions = initWFDecisionOptions(rejectNodeNumbers); wfJointTask.setDecisionOptions(decisionOptions); //单据设置 WFBillSetting billSetting = new WFBillSetting(); billSetting.setMobilFormKey("anquan$"); billSetting.setFormKey(getView().getFormShowParameter().getFormId()); wfJointTask.setBillSetting(billSetting); //一票通过 wfJointTask.setBusinessModel("passByOne"); return wfJointTask; }
自动节点的创建如下:
private WFAutoTask initWFAutoTask(WFProcess wfProcess) { WFAutoTask wfAutoTask = new WFAutoTask(wfProcess); LocaleString name = new LocaleString(); name.put(Lang.zh_CN.name(), ResManager.loadKDString("自由流自动节点", "FreeFlowPlugin_11", WF_UNITTEST)); name.put(Lang.zh_TW.name(), ResManager.loadKDString("自由流自动节点", "FreeFlowPlugin_11", WF_UNITTEST)); name.put(Lang.en_US.name(), "freeflowWFAutoTask"); wfAutoTask.setName(name); WFAutoTaskExtItf service = new WFAutoTaskExtItf(); ListextItf = new ArrayList<>(); JSONObject plugin1 = new JSONObject(); plugin1.put("type", CLASS); plugin1.put(VALUE, "kd.bos.workflow.design.demo.FreeFlowExtItf"); extItf.add(plugin1.toString()); JSONObject plugin2 = new JSONObject(); plugin2.put("type", OPERATION); JSONObject pluginValue = new JSONObject(); pluginValue.put("forward_name", ResManager.loadKDString("保存", "FreeFlowPlugin_12", WF_UNITTEST)); pluginValue.put("forward", "save"); plugin2.put(VALUE, pluginValue); extItf.add(plugin2.toString()); service.setExtItf(extItf); wfAutoTask.setService(service); return wfAutoTask; }
其中参与人的创建有4种,如下:
//关系 private WFParticipantEntity getParticipant1() { WFParticipantEntity paritcipant = new WFParticipantEntity(); paritcipant.setReferencePerson("ENTI_creator"); paritcipant.setType("relation"); paritcipant.setPersonRelation("self"); paritcipant.setReportType("admin_org"); return paritcipant; } //指定人 private WFParticipantEntity getParticipant2() { WFParticipantEntity paritcipant = new WFParticipantEntity(); paritcipant.setType("person"); paritcipant.setValue("3032311,101493"); return paritcipant; } //角色 private WFParticipantEntity getParticipant3() { WFParticipantEntity paritcipant = new WFParticipantEntity(); paritcipant.setRoleId("887560420028580864"); paritcipant.setType("role"); paritcipant.setValue("wyrtest"); paritcipant.setBusinessOrgField("ENTI_creator.entryentity.dpt"); return paritcipant; } //插件 private WFParticipantEntity getParticipant4() { WFParticipantEntity paritcipant = new WFParticipantEntity(); paritcipant.setType("plugin"); JSONObject plugin = new JSONObject(); plugin.put("type", CLASS); plugin.put(VALUE, "kd.bos.workflow.design.demo.FreeFlowDynParticipantPlugin"); paritcipant.setValue(plugin.toString()); return paritcipant; }
发起流程时,构建的自由流运行效果如下:
步骤二:流程审批中,向指定节点后插入多个节点。
在进入流程节点时,注册插件。在插件里构建自由流对象,放入流程变量中,如下图所示:
相关代码示例如下:
public class FreeFlowTestPlugin1 implements IWorkflowPlugin{ @Override public void notify(AgentExecution execution) { WFProcess wfProcess = initWfProcess(execution); execution.setVariable(getFreeFlowNodeKey(execution.getCurrentFlowElement().getId()),SerializationUtils.toJsonString(wfProcess)); } }
运行效果如下:
4 常见问题
Q1:苍穹工作流自由流程,是否提供界面化的配置功能?
A1:目前标准产品不提供,有项目化的实施方案可供参考。
Q2:基于苍穹工作流构建一条标准的自由流程,需要多少实施成本?
A2:熟悉苍穹工作流的技术人员,可在3个工作日内构建出一个节点不超过15个的中等复杂度流程。
5 相关链接
更多苍穹工作流自由流程相关资料,可参考如下链接:
#往期推荐#
更多精彩内容,“码”上了解!↓
苍穹工作流那些事 之 自由流程
本文2024-09-23 00:54:30发表“云苍穹知识”栏目。
本文链接:https://wenku.my7c.com/article/kingdee-cangqiong-142522.html