插件实现审核后自动下推,反审核自动删除下游单据原创
7人赞赏了该文章
1,530次浏览
编辑于2022年07月28日 15:53:02
审核后自动下推步骤:
创建单据转换规则,配置字段映射关系
审核菜单操作服务中配置自动下推服务
反审核自动删除下游单据则需要使用插件来实现:
如果下游单据存在,反审核上游单据会提示存在下游单据关联关系导致无法反审核。
在反审核服务操作中挂上服务插件来实现反审核自动删除下游单据,代码如下:
/// <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人打赏
还没有人打赏,快来当第一个打赏的人吧!
推荐阅读
您的鼓励与嘉奖将成为创作者们前进的动力,如果觉得本文还不错,可以给予作者创作打赏哦!
请选择打赏金币数 *
10金币20金币30金币40金币50金币60金币
可用金币: 0