反审核操作插件中触发工作流,让反审核也走工作流!原创
金蝶云社区-老杂鱼
老杂鱼
13人赞赏了该文章 1,950次浏览 未经作者许可,禁止转载编辑于2021年03月05日 18:22:55

最近看到一个配置反审核操作触发工作流的教程,就想能不能插件中直接调用生成工作流方法直接触发工作流,于是便反编译大佬代码尝试了一下,结果还真有方法,下面分享给大家:

  1. 设计采购申请单工作流正向流程

    image.png

  2. 设计采购申请单工作流反向流程

    image.png

  3. 设计流程设置中心流程启动条件

    image.png

4.代码部分

using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Linq;

using System.Text;

using System.Text.RegularExpressions;

using System.Transactions;

using Kingdee.BOS;

using Kingdee.BOS.App;

using Kingdee.BOS.App.Core;

using Kingdee.BOS.App.Core.ScheduleService;

using Kingdee.BOS.App.Data;

using Kingdee.BOS.Business.Bill.Operation;

using Kingdee.BOS.Business.Bill.Operation.Workflow;

using Kingdee.BOS.Contracts;

using Kingdee.BOS.Core.DependencyRules;

using Kingdee.BOS.Core.DynamicForm;

using Kingdee.BOS.Core.DynamicForm.PlugIn;

using Kingdee.BOS.Core.DynamicForm.PlugIn.Args;

using Kingdee.BOS.Core.List;

using Kingdee.BOS.Core.Metadata;

using Kingdee.BOS.Core.Metadata.StatusElement;

using Kingdee.BOS.Core.Schedules;

using Kingdee.BOS.KDThread;

using Kingdee.BOS.Log;

using Kingdee.BOS.Orm;

using Kingdee.BOS.Orm.DataEntity;

using Kingdee.BOS.Resource;

using Kingdee.BOS.Scripting;

using Kingdee.BOS.ServiceHelper;

using Kingdee.BOS.Util;

using Kingdee.BOS.Workflow.App.Core;

using Kingdee.BOS.Workflow.App.Core.Repositories;

using Kingdee.BOS.Workflow.Assignment;

using Kingdee.BOS.Workflow.Engine;

using Kingdee.BOS.Workflow.Enums;

using Kingdee.BOS.Workflow.Hosting;

using Kingdee.BOS.Workflow.Models;

using Kingdee.BOS.Workflow.Models.EnumStatus;

using Kingdee.BOS.Workflow.Models.Template;

using Kingdee.BOS.Workflow.Providers;

using Kingdee.BOS.Workflow.ServiceHelper;


namespace MyTestProject

{

    [Kingdee.BOS.Util.HotUpdate]

    [Description("反审核操作触发工作流")]

    public class AuditSPL : AbstractOperationServicePlugIn

    {

        public override void OnPreparePropertys(PreparePropertysEventArgs e)

        {

            base.OnPreparePropertys(e);

            e.FieldKeys.Add("F_YOL_LC");//是否生成流程

        }

        public override void BeginOperationTransaction(BeginOperationTransactionArgs e)

        {

          //  BillTools datas = new BillTools();

            base.BeginOperationTransaction(e);

            if (this.FormOperation.Operation=="UnAudit")

            {

                foreach (var bill in e.DataEntitys)

                {

                    if (Convert.ToBoolean( bill["F_YOL_LC"])==true)

                    {

                        bill["F_YOL_LC"] = false;

                        Kingdee.BOS.ServiceHelper.BusinessDataServiceHelper.Save(this.Context, bill);

                    }

                    else

                    {

                        List<DynamicObject> lists = new List<DynamicObject>();

                        //创建流程实例 select a.FTMPID 100003  ,FTMPDETAILID 100007 ,FVERSIONID 6041c6395a2034  from  t_WF_Template  a inner join t_wf_PrcLaunchConfig b on a.FTmpID=b.FTmpID--流程配置中心表 

                        var sl = this.CreateProcessInstance(this.Context, this.BusinessInfo, "100003", "100007", "6041c6395a2034", bill["Id"], false, lists, 0, null, "");


                        bool result = this.StartWorkflow(this.Context, false, sl, this.GetMessageSendMode(this.Context));

                       // bool result = datas.TiggerWorkFlow(this.Context, this.BusinessInfo, "100003", "100007", "6041c6395a2034", bill["Id"].ToString(), 0);

                        if (result == true)

                        {

                            bill["F_YOL_LC"] = true;

                            Kingdee.BOS.ServiceHelper.BusinessDataServiceHelper.Save(this.Context, bill);

                            e.CancelOperation = true;

                        }

                    }

                   


                }

            }

            


        }

     


        private ProcessInstance CreateProcessInstance(Context ctx, BusinessInfo info, string templeteId, string tempDetailId, string verId, object pkValue, bool writeProcessLog, List<DynamicObject> storeList, int? originatorPostId = null, string submitOpinion = null, string submitStatusKey = "")

        {


            WorkflowModelService workflowModelService = new WorkflowModelService();

            CacheProcess cacheProcessByVersionId = workflowModelService.GetCacheProcessByVersionId(ctx, verId);

            if (cacheProcessByVersionId == null)

            {

                throw new Exception(ResManager.LoadKDString("未找到对应的流程定义,版本Id:", "002525030016300", SubSystemType.BOS, new object[0]) + verId);

            }

            if (info == null)

            {

                throw new Exception(ResManager.LoadKDString("_businessInfo 未赋值。", "002525030021211", SubSystemType.BOS, new object[0]));

            }

            BOSFlowRepository bosflowRepository = new BOSFlowRepository(ctx);

            WorkflowEngine workflowEngine = new WorkflowEngine(cacheProcessByVersionId.Process, ctx, bosflowRepository);

            ProcessInstance processInstance = workflowEngine.CreateProcessInstance();

            processInstance.TrySetMember("FormId", info.GetForm().Id);

            processInstance.TrySetMember("FormName", info.GetForm().Name.ToString());

            processInstance.TrySetMember("KeyValue", pkValue.ToString());

            processInstance.ProcDefId = cacheProcessByVersionId.ProcDefId;

            processInstance.VersionId = verId;

            processInstance.OriginatorId = ctx.UserId;

            processInstance.TempleteId = templeteId;

            processInstance.TempDetailId = tempDetailId;

            ProcessInstance processInstance2 = processInstance;

            int? num = originatorPostId;

            processInstance2.OriginatorPostId = ((num != null) ? new long?((long)num.GetValueOrDefault()) : null);

            processInstance.CreatedTime = DateTime.Now;

            processInstance.Summary = "123";

            processInstance.SubmitOpinion = submitOpinion;

            processInstance.SubmitStatusKey = ((submitStatusKey == null) ? "" : submitStatusKey);

            this.InitProcInst(processInstance, ctx);

            bosflowRepository.CreateProcessInstance(processInstance);

            string workflowStartActivityCheckId = this.GetWorkflowStartActivityCheckId(info.GetForm().Id, pkValue);

            this.AddStartBackMqStore(ctx, processInstance, workflowStartActivityCheckId, storeList);

            return processInstance;

        }


        public string GetWorkflowStartActivityCheckId(string formId, object pkValue)

        {

            return formId + "_" + pkValue.ToString();

        }


        public void InitProcInst(ProcessInstance procInst, Context ctx)

        {

            object obj;

            procInst.TryGetMember("FormId", out obj);

            object obj2;

            procInst.TryGetMember("KeyValue", out obj2);

            if (obj == null || string.IsNullOrWhiteSpace(obj.ToString()) || obj2 == null || string.IsNullOrWhiteSpace(obj2.ToString()))

            {

                throw new Exception(ResManager.LoadKDString("流程实例的单据变量和单据编码变量不能为空", "002525030016507", SubSystemType.BOS, new object[0]));

            }

            procInst.Number = "CGSSD" + "_" + DateTime.Now.ToString("yyyy_MM_dd");//实例名称,一定要包含"_"

            string strSQL = "\r\n                insert into T_WF_PIBIMap(FId, FProcInstId, FObjectTypeId, FKeyValue)\r\n                values(@FId, @FProcInstId, @FObjectTypeId, @FKeyValue)";

            IDBService service = ServiceHelper.GetService<IDBService>();

            List<SqlParam> list = new List<SqlParam>();

            list.Add(new SqlParam("@FId", KDDbType.AnsiString, service.GetSequenceString(1)[0]));

            list.Add(new SqlParam("@FProcInstId", KDDbType.AnsiString, procInst.MapInstanceId));

            list.Add(new SqlParam("@FObjectTypeId", KDDbType.AnsiString, obj.ToString()));

            list.Add(new SqlParam("@FKeyValue", KDDbType.AnsiString, obj2.ToString()));

            DBUtils.Execute(ctx, strSQL, list);

        }


        public bool StartWorkflow(Context ctx, bool writeProcessLog, ProcessInstance pi, MessageSendMode messageSendMode)

        {



            if (messageSendMode == MessageSendMode.Sync || messageSendMode == MessageSendMode.Async)

            {


                try

                {

                    this.SendSyncMessage<StartBackJobService>(ctx, pi, null, true);

                }

                catch (Exception)

                {


                    return false;

                }

                return true;

            }

            else

            {

                try

                {

                    this.SendAsyncMessage<StartBackJobService>(ctx, messageSendMode, pi, null);

                }

                catch (Exception)

                {


                    return false;

                }

                return true;


            }


        }

        public void AddStartBackMqStore(Context ctx, ProcessInstance pi, string startActivityInstId, List<DynamicObject> storeList)

        {

            AsyncMessage msg = new AsyncMessage

            {

                Context = ctx,

                ServiceType = typeof(StartBackJobService).AssemblyQualifiedName,

                DataInfo = pi

            };

            this.AddMqStoreList(ctx, pi.CreatedTime, storeList, startActivityInstId, msg);

        }

        public void AddMqStoreList(Context ctx, DateTime executedTime, List<DynamicObject> storeList, string actInstId, AsyncMessage msg)

        {

            storeList.Add(new MapStateMqStore

            {

                MsgData = SerializatonUtil.Serialize(msg),

                SendUserId = ctx.UserId,

                CREATEDATE = executedTime,

                ActInstId = actInstId,

                Status = MapStateMqStatus.Untreated

            }.DataEntity);

        }

        public Exception SendAsyncMessage<T>(Context ctx, MessageSendMode mode, object dataInfo, Action method)

        {

            AsyncMessage msg = new AsyncMessage

            {

                Context = ctx,

                DataInfo = dataInfo,

                ServiceType = typeof(T).AssemblyQualifiedName

            };

            return this.SendAsyncMessage(msg, mode, method);

        }

        public Exception SendAsyncMessage(AsyncMessage msg, MessageSendMode mode, Action method)

        {

            Exception result = null;

            if (method != null)

            {

                method();

            }

            try

            {

                MessageQueueAsyncService messageQueueAsyncService = new MessageQueueAsyncService();

                messageQueueAsyncService.Send(msg);

            }

            catch (Exception ex)

            {

                result = ex;

                Logger.Error("WF", ex.Message, ex);

            }

            return result;

        }


        public void SendSyncMessage<T>(Context ctx, object dataInfo, Action method, bool startNewThread = true)

        {

            if (startNewThread)

            {

                MainWorker.QuequeTask(ctx, delegate ()

                {

                    T t2 = Activator.CreateInstance<T>();

                    if (method != null)

                    {

                        method();

                    }

                    ((IAsyncService)((object)t2)).Excute(ctx, dataInfo);

                }, delegate (AsynResult result)

                {

                    if (!result.Success && result.Exception != null)

                    {


                    }

                });

                return;

            }

            try

            {

                T t = Activator.CreateInstance<T>();

                using (KDTransactionScope kdtransactionScope = new KDTransactionScope(TransactionScopeOption.Required))

                {

                    if (method != null)

                    {

                        method();

                    }

                    ((IAsyncService)((object)t)).Excute(ctx, dataInfo);

                    kdtransactionScope.Complete();

                }

            }

            catch (Exception)

            {


                throw;

            }

        }


        public MessageSendMode GetMessageSendMode(Context ctx)

        {

            bool sysParaWriteProcessLogger = this.GetSysParaWriteProcessLogger(ctx);

            //   LogRepository.WriteBOSWorkflowLog(ctx, "GetMessageSendMode", 10, "begin GetMessageSendMode", sysParaWriteProcessLogger);

            SystemParameterService systemParameterService = new SystemParameterService();

            object paramter = systemParameterService.GetParamter(ctx, 0L, 0L, "WF_SystemParameter", "FlowProcMode", 0L);

            //    LogRepository.WriteBOSWorkflowLog(ctx, "GetMessageSendMode", 20, string.Format("FlowProcMode = {0}", paramter), sysParaWriteProcessLogger);

            MessageSendMode messageSendMode = (MessageSendMode)Convert.ToInt32(paramter);

            if (messageSendMode != MessageSendMode.MSMQ)

            {

                return messageSendMode;

            }

            else

            {

                return MessageSendMode.Async;

            }

        }


        public bool GetSysParaWriteProcessLogger(Context ctx)

        {

            return ObjectUtils.Object2Bool(ServiceHelper.GetService<ISystemParameterService>().GetParamter(ctx, 0L, 0L, "WF_SystemParameter", "FWriteLog", 0L), false);

        }

        public class StartBackJobService : IAsyncService

        {


            public void Excute(Context ctx, object arg)

            {


                this.StartWorkflowExecute(ctx, (ProcessInstance)arg);

            }



            public string GetDataInfo(object arg)

            {

                ProcessInstance processInstance = (ProcessInstance)arg;

                StringBuilder stringBuilder = new StringBuilder();

                stringBuilder.AppendFormat(ResManager.LoadKDString("流程实例Id:{0}, 流程编码:{1}, 发起人Id:{2}", "002525030023196", SubSystemType.BOS, new object[0]), processInstance.MapInstanceId, processInstance.Number, processInstance.OriginatorId.ToString());

                stringBuilder.Append(" \r\n");

                foreach (VariableInstance variableInstance in processInstance.VariableInstances)

                {

                    stringBuilder.AppendFormat(ResManager.LoadKDString("变量名:{0}, 值:{1}", "002525030023199", SubSystemType.BOS, new object[0]), variableInstance.Name, variableInstance.Value);

                    stringBuilder.Append(" \r\n");

                }

                return stringBuilder.ToString();

            }


            public void StartWorkflowExecute(Context ctx, ProcessInstance procInst)

            {


                WorkflowModelService workflowModelService = new WorkflowModelService();

                CacheProcess cacheProcessByVersionId = workflowModelService.GetCacheProcessByVersionId(ctx, procInst.VersionId);

                BOSFlowRepository repository = new BOSFlowRepository(ctx);

                object obj = "";

                procInst.TryGetMember("FormId", out obj);

                object obj2 = "";

                procInst.TryGetMember("KeyValue", out obj2);

                using (KDTransactionScope kdtransactionScope = new KDTransactionScope(TransactionScopeOption.Required))

                {


                    WorkflowEngine workflowEngine = new WorkflowEngine(cacheProcessByVersionId.Process, ctx, repository);

                    IDictionary<string, object> variables = null;

                    workflowEngine.Start(procInst, variables);

                    kdtransactionScope.Complete();

                }

            }

        }



    }

}


5.说明

  1.审批流审批项处表单操作灰色锁定,没办法绑定反审核操作,所以使用的是工作流;2.代码只是单张单据测试,实际情况适当进行更改;3.很多方法也不知道什么意思就是无脑调用;4.在BeginOperationTransaction事件中生成单据的工作流,如果生成成功,则 e.CancelOperation = true;取消本次操作,由生成的工作流去完成反审核操作,所以代码里判断是是否生成工作流;6.如何取消还不知道。


赞 13