D365中当一个员工身居多职或者承担多个角色时,针对这样的场景,我们在配置审批流过程当中,难免会遇到,在配置的审批节点时,同一个人会出现在多个审批节点中,用户就会出现,同一张单需要进行多次审批,为了避免这种情况,需要通过对标准的审批流进行二次开发,涉及的开发主要需要扩展两个关键的类
1,SysWorkflowWorkItem
由于需要调用标准的SysWorkflowWorkItem的静态方法create来创建工作项,但是create方法又是private的,所以我们只能利用反射的机制来进行调用
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掉已经审核过的审核人的工作项
- 当审核策略设置为大多数人审批或者所有人审批时,并且审批流流转到当前的节点存在多个审核人,并且其中的审核人,在前面的节点已经审批过,此是,我们应该将此节点将审核过的人的工作项自动审批,不需要审批人手工再次进行审批
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遍历不能修改集合的元素
标签:Workflow,workItemActivityContext,System,D365,审批,审核,workItemTable,节点 From: https://www.cnblogs.com/dingkui/p/16645936.html