ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

D365: Workflow避免同一审核人多次审批

2022-09-01 11:32:23  阅读:159  来源: 互联网

标签:Workflow workItemActivityContext System D365 skip 审批 审核 workItemTable 节点


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,skip,审批,审核,workItemTable,节点
来源: https://www.cnblogs.com/dingkui/p/16645936.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有