D365: Workflow避免同一审核人多次审批
D365中当一个员工身居多职或者承担多个角色时,针对这样的场景,我们在配置审批流过程当中,难免会遇到,在配置的审批节点时,同一个人会出现在多个审批节点中,用户就会出现,同一张单需要进行多次审批,为了避免这种情况,需要通过对标准的审批流进行二次开发,涉及的开发主要需要扩展两个关键的类
1,SysWorkflowWorkItem
由于需要调用标准的SysWorkflowWorkItem的静态方法create来创建工作项,但是create方法又是private的,所以我们只能利用反射的机制来进行调用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | using System.Reflection; [ExtensionOf(classStr(SysWorkflowWorkItem))] final class SysWorkflowWorkItemVya_Extension { public void callCreateWorkItems(Microsoft.Dynamics.AX.Framework.Workflow.Runtime.WorkItemActivityContext _workItemActivityContext, WorkflowWorkItemClaimed _isClaimed, Delimiter _workflowDelimiter = ',' ) { //int n; //设置方法参数 System.Object[] parametersArray = new System.Object[3](); parametersArray.SetValue(_workItemActivityContext, 0); parametersArray.SetValue(_isClaimed, 1); parametersArray.SetValue(_workflowDelimiter, 2); var bindFlags = BindingFlags::NonPublic | BindingFlags::Static; System.Type type = this .GetType(); var methodsInfo = type.GetMethods(bindFlags); for ( int n = 0; n < methodsInfo.get_Length(); n++) { System.Reflection.MethodInfo methodInfo = methodsInfo.getValue(n); if (methodInfo.Name == staticMethodStr(SysWorkflowWorkItem, create)) { System.Object[] parametersList = methodInfo.GetParameters(); if (parametersList.Length == 3) { methodInfo.Invoke( this , parametersArray); break ; } } } } } |
2,SysWorkflowWorkItemHelper
标准的审批流逻辑大部分代码,微软不允许我们进行扩展,但是给我们预留了一个框架类SysWorkflowWorkItemHelper,我们通过这个类里面的两个方法skipWorkItem,removeWorkItems来对审批节点创建的工作项进行skip和remove处理来达到上面的需求
扩展skipWorkItem,在方法体中,我们主要是需要做一个判断,如果当前的待审核人,在之前的审批节点中已经审批过此单,我们就不需要为此待审批人继续创建待审工作项
扩展removeWorkItem,由于审批流中可以设置不同的审批策略,可以设置审批节点,需要单个人审批,大多数人审批或者所有人审批。
针对不同的策略,我们需要在扩展的removeWorkItem方法中,分别进行处理
- 当审批策略设置为单个人审批时,并且审批流流转到当前的节点只有一个审核人,并且审核人,在前面的节点已经审批过,此是,我们应该将此节点自动审批,不需要审批人手工再次进行审批
- 当审批策略设置为单个人审批时,并且审批流流转到当前的节点存在多个审核人,并且其中的审核人,在前面的节点已经审批过,此是,我们应该skip掉已经审核过的审核人的工作项
- 当审核策略设置为大多数人审批或者所有人审批时,并且审批流流转到当前的节点存在多个审核人,并且其中的审核人,在前面的节点已经审批过,此是,我们应该将此节点将审核过的人的工作项自动审批,不需要审批人手工再次进行审批
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 | using Microsoft.Dynamics.AX.Framework.Workflow.Runtime; [ExtensionOf(classStr(SysWorkflowWorkItemHelper))] final class SysWorkflowWorkItemHelperVya_Extension { public static boolean skipWorkItem(WorkItemActivityContext _workItemActivityContext) { SysWorkflowElement sysWorkflowElement; WorkflowWorkItemTable workItemTable; WorkflowElementEventArgs elementEventArgs; WorkflowWorkItemsEventArgs workItemEventArgs; UserId curUserId; boolean skip = next skipWorkItem(_workItemActivityContext); curUserId = _workItemActivityContext.User.UserId; select firstonly workItemTable where workItemTable.ConfigurationId == _workItemActivityContext.ConfigurationId && workItemTable.CorrelationId == _workItemActivityContext.WorkflowContext.WorkflowCorrelationId && workItemTable.RootCorrelationId == _workItemActivityContext.WorkflowContext.RootCorrelationId && workItemTable.UserId == _workItemActivityContext.User.UserId && workItemTable.Status == WorkflowWorkItemStatus::Completed; if (workItemTable.RecId) { skip = true ; } return skip; } public static void removeWorkItems(WorkItemActivityContextCollection _workItems) { Microsoft.Dynamics.AX.Framework.Workflow.Runtime.WorkItemActivityContext workItemActivityContext; System.Collections.IEnumerator enumerator; WorkflowWorkItemTable workItemTable; WorkflowStepTable workflowStepTable; int i; Array array; boolean skip; next removeWorkItems(_workItems); for (i = 0; i < _workItems.Count; i++) { workItemActivityContext = _workItems.get_ITEM(i); skip = SysWorkflowWorkItemHelper::skipWorkItem(workItemActivityContext); if (skip) { if (_workItems.Count == 1) { workItemTable = WorkflowWorkItemTable::findActivityInstanceId(workItemActivityContext.get_ActivityId()); if (workItemTable.RecId == 0) { new SysWorkflowWorkItem().callCreateWorkItems(workItemActivityContext, NoYes::Yes); } workItemTable = WorkflowWorkItemTable::findActivityInstanceId(workItemActivityContext.get_ActivityId()); if (workItemTable) { WorkflowWorkItemActionManager::dispatchWorkItemAction( workItemTable, "Auto Approve" , workItemTable.UserId, WorkflowWorkItemActionType::Complete, workItemTable.MenuItemName); } } else { workflowStepTable = WorkflowStepTable::find(workItemActivityContext.StepActivityId); if (workflowStepTable.CompletionPolicy == WorkflowStepCompletionPolicy::Single) { _workItems.Remove(workItemActivityContext); } else { workItemTable = WorkflowWorkItemTable::findActivityInstanceId(workItemActivityContext.get_ActivityId()); if (workItemTable.RecId == 0) { new SysWorkflowWorkItem().callCreateWorkItems(workItemActivityContext, NoYes::Yes); } workItemTable = WorkflowWorkItemTable::findActivityInstanceId(workItemActivityContext.get_ActivityId()); if (workItemTable) { WorkflowWorkItemActionManager::dispatchWorkItemAction( workItemTable, "Auto Approve" , workItemTable.UserId, WorkflowWorkItemActionType::Complete, workItemTable.MenuItemName); } } } } } } } |
难点:
- 找到扩展的对象
- 由于workflow大部分逻辑我们无法扩展且不能进行直接调用,需要利用反射的机制进行处理
- 遍历待审核工作项,集合不能用System.Collections.IEnumerator进行遍历,一定要用for循环,因为System.Collections.IEnumerator遍历不能修改集合的元素
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek 开源周回顾「GitHub 热点速览」
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· AI与.NET技术实操系列(二):开始使用ML.NET
· 单线程的Redis速度为什么快?