插件实现审核后自动下推,反审核自动删除下游单据原创
金蝶云社区-何某人
何某人
7人赞赏了该文章 1,669次浏览 未经作者许可,禁止转载编辑于2022年07月28日 15:53:02

审核后自动下推步骤:

  1. 创建单据转换规则,配置字段映射关系

  2. 审核菜单操作服务中配置自动下推服务

    图片.png


反审核自动删除下游单据则需要使用插件来实现:

如果下游单据存在,反审核上游单据会提示存在下游单据关联关系导致无法反审核。


在反审核服务操作中挂上服务插件来实现反审核自动删除下游单据,代码如下:

/// <summary>
        /// 事务内删除,则需要先删除验证,如果是事务外删除则不需要加此事件
        /// </summary>
        /// <param name="e"></param>
        public override void OnAddValidators(AddValidatorsEventArgs e)
        {
            base.OnAddValidators(e);
            e.Validators.RemoveAll(x => x.GetType().ToString().EndsWith("IsPushValidator"));
        }

        #region DEMO1
        public override void OnPreparePropertys(PreparePropertysEventArgs e)
        {
            foreach (var entity in this.BusinessInfo.Entrys)
            {
                if (entity is SubEntryEntity)
                {
                    // 子单据体不能作为关联主实体,忽略掉                    
                    continue;
                }
                // 添加单据体主键字段               
                if (entity is EntryEntity && entity.DynamicProperty != null)
                {
                    e.FieldKeys.Add(string.Format("{0}_{1}", entity.Key, entity.EntryPkFieldName));
                }
            }
        }

        public override void EndOperationTransaction(EndOperationTransactionArgs e)
        {
            // 本单主键为字符串类型,略过           
            if (this.BusinessInfo.GetForm().PkFieldType == EnumPkFieldType.STRING)
            {
                return;
            }
            // 把单据数据包,展开为按实体Key为标识存储的数据字典            
            ExtendedDataEntitySet dataEntitySet = new ExtendedDataEntitySet();
            dataEntitySet.Parse(e.DataEntitys, this.BusinessInfo);
            // 对各单据体进行循环,分别扫描下游单据,逐单删除           
            foreach (var entity in this.BusinessInfo.Entrys)
            {
                // 判断此实体,是否需要扫描下游单据                
                if (this.IgnoreEntity(entity)) continue;
                // 取实体数据集合               
                ExtendedDataEntity[] rows = dataEntitySet.FindByEntityKey(entity.Key);
                if (rows == null)
                {
                    // 容错                    
                    continue;
                }
                // 取实体的业务流程数据                
                HashSet<long> entityIds = new HashSet<long>();
                foreach (var row in rows)
                {
                    long entityId = Convert.ToInt64(row.DataEntity[0]);
                    entityIds.Add(entityId);
                }
                BusinessFlowInstanceCollection bfInstances = this.LoadBFInstance(entity.Key, entityIds);
                if (bfInstances == null || bfInstances.Count == 0)
                {
                    // 无关联的业务流程实例,略过                    
                    continue;
                }
                // 从业务流程实例中,分析出本单据体的下游单据内码:按目标单据体分好组                
               
 Dictionary<string, HashSet<long>> dctTargetEntityIds = 
this.GetTargetEntityIds(entity, entityIds, bfInstances);
                // 对各种下游单据进行循环,逐个删除                
                foreach (var targetBill in dctTargetEntityIds)
                {
                    IOperationResult deleteResult = this.DeleteTargetBill(targetBill.Key, targetBill.Value);
                    if (CheckOpResult(deleteResult) == false)
                    {
                        // 删除失败,无需继续,退出                        
                        return;
                    }
                }
            }
        }


        private bool IgnoreEntity(Entity entity)
        {
            if (entity is SubEntryEntity || entity is SubHeadEntity)
            {
                // 子单据头、单据体不能作为关联主实体,忽略掉               
                return true;
            }
            if (entity.DynamicObjectType == null)
            {
                // 容错                
                return true;
            }
            return false;
        }

        private BusinessFlowInstanceCollection LoadBFInstance(string entityKey, HashSet<long> entityIds)
        {
           
 LoadInstancesByEntityIdArgs args = new 
LoadInstancesByEntityIdArgs(this.BusinessInfo.GetForm().Id, entityKey, 
entityIds.ToArray());
            IBusinessFlowDataService bfDataServer = ServiceHelper.GetService<IBusinessFlowDataService>();
            var bfInstances = bfDataServer.LoadInstancesByEntityId(this.Context, args);
            return bfInstances;
        }

       
 private Dictionary<string, HashSet<long>> 
GetTargetEntityIds(Entity entity, HashSet<long> entityIds, 
BusinessFlowInstanceCollection bfInstances)
        {
            Dictionary<string, HashSet<long>> dctTargetEntityIds = new 
Dictionary<string, HashSet<long>>();
            IBusinessFlowService bfService = ServiceHelper.GetService<IBusinessFlowService>();
            TableDefine srcTableDefine = bfService.LoadTableDefine(this.Context, this.BusinessInfo.GetForm().Id, entity.Key);
            // 逐个实例查找本单的下游单据体内码            
            foreach (var instance in bfInstances)
            {
                // 首先找到业务流程实例中,本单所在的节点                
                var srcNodes = instance.SerarchTargetFormNodes(srcTableDefine.TableNumber);
                foreach (RouteTreeNode srcNode in srcNodes)
                {
                    if (entityIds.Contains(srcNode.Id.EId))
                    {
                        // 找到了本单所在的节点,按类别输出其下游节点:                        
                        foreach (RouteTreeNode targetNode in srcNode.ChildNodes)
                        {
                            if (dctTargetEntityIds.Keys.Contains(targetNode.Id.Tbl) == false)
                            {
                                dctTargetEntityIds.Add(targetNode.Id.Tbl, new HashSet<long>());
                            }
                            if (dctTargetEntityIds[targetNode.Id.Tbl].Contains(targetNode.Id.EId) == false)
                            {
                                dctTargetEntityIds[targetNode.Id.Tbl].Add(targetNode.Id.EId);
                            }
                        }
                    }
                }
            }
            return dctTargetEntityIds;
        }

        private IOperationResult DeleteTargetBill(string tableNumber, HashSet<long> entityIds)
        {
            IBusinessFlowService bfService = ServiceHelper.GetService<IBusinessFlowService>();
            TableDefine tableDefine = bfService.LoadTableDefine(this.Context, tableNumber);
            // 读取下游单据的元数据            
            IMetaDataService metaService = ServiceHelper.GetService<IMetaDataService>();
            FormMetadata meta = metaService.Load(this.Context, tableDefine.FormId) as FormMetadata;
            // 根据下游单据体的内码,读取单据内码            
            HashSet<long> billIds = this.LoadTargetBillIds(meta.BusinessInfo, tableDefine.EntityKey, entityIds);
            object[] pkValues = (from p in billIds select (object)p).ToArray();
            // 调用删除服务,删除单据            
            IDeleteService deleteService = ServiceHelper.GetService<IDeleteService>();
            IOperationResult deleteResult = deleteService.Delete(this.Context, meta.BusinessInfo,
                pkValues, this.Option);
            return deleteResult;
        }

       
 private HashSet<long> LoadTargetBillIds(BusinessInfo 
targetBusinessInfo, string entityKey, HashSet<long> entityIds)
        {
            // 根据单据体内码,读取取下游单据的单据内码            
            HashSet<long> billIds = new HashSet<long>();
            Entity entity = targetBusinessInfo.GetEntity(entityKey);
            if (entity is HeadEntity)
            {
                foreach (var billId in entityIds)
                {
                    billIds.Add(billId);
                }
            }
            else
            {
                string entityPKFieldNameAs = string.Concat(entity.Key, "_", entity.EntryPkFieldName);
                QueryBuilderParemeter queryParem = new QueryBuilderParemeter()
                {
                    FormId = targetBusinessInfo.GetForm().Id,
                    BusinessInfo = targetBusinessInfo,
                };
                queryParem.SelectItems.Add(new SelectorItemInfo(targetBusinessInfo.GetForm().PkFieldName));
                queryParem.SelectItems.Add(new SelectorItemInfo(entityPKFieldNameAs));
                queryParem.ExtJoinTables.Add(
                    new ExtJoinTableDescription()
                    {
                        TableName = "table(fn_StrSplit(@EntryPKValue,',',1))",
                        TableNameAs = "sp",
                        FieldName = "FID",
                        ScourceKey = entityPKFieldNameAs,
                    });
                queryParem.SqlParams.Add(new SqlParam("@EntryPKValue", KDDbType.udt_inttable, entityIds.ToArray()));
                IQueryService queryService = ServiceHelper.GetService<IQueryService>();
                DynamicObjectCollection rows = queryService.GetDynamicObjectCollection(this.Context, queryParem);
                foreach (var row in rows)
                {
                    long billId = Convert.ToInt64(row[0]);
                    if (billIds.Contains(billId) == false)
                    {
                        billIds.Add(billId);
                    }
                }
            }
            return billIds;
        }

        private bool CheckOpResult(IOperationResult opResult)
        {
            bool isSuccess = false;
            if (opResult.IsSuccess == true)
            {
                // 操作成功                
                isSuccess = true;
            }
            else
            {
                // 操作失败,拼接失败原因,然后抛出中断      
                opResult.MergeValidateErrors();
                if (opResult.OperateResult == null)
                {
                    throw new KDBusinessException("DeleteTargetBill-001", "未知原因导致自动删除下游单据失败!");
                }
                else
                {
                    StringBuilder sb = new StringBuilder();
                    sb.AppendLine("自动删除下游单据失败,失败原因:");
                    foreach (var operateResult in opResult.OperateResult)
                    {
                        sb.AppendLine(operateResult.Message);
                    }
                    throw new KDBusinessException("DeleteTargetBill-002", sb.ToString());
                }
            }
            return isSuccess;
        }

        #endregion

以上代码是通用,只需要在反审核操作中挂上此插件便可自动删除下游单据


参考资料:

https://vip.kingdee.com/article/24549?productLineId=1


https://vip.kingdee.com/article/187289797432491008?productLineId=1




图标赞 7
7人点赞
还没有人点赞,快来当第一个点赞的人吧!
图标打赏
0人打赏
还没有人打赏,快来当第一个打赏的人吧!