电脑桌面
添加蚂蚁七词文库到电脑桌面
安装后可以在桌面快捷访问

业务流.全流程跟踪.源单和下游单显示不同的原因和二开方案

来源:金蝶云社区作者:金蝶2024-09-237

业务流.全流程跟踪.源单和下游单显示不同的原因和二开方案

【场景】采购订单下推采购入库单,采购订单下推付款申请单 采购订单的全流程图 ![1679457091489.webp](/download/0100d2265faa09cf4711b5eb786447efaa6c.webp) 但是采购入库单看不到应付单,应付单看不到采购入库单 【原理】在系统的理解中,子单据只能看到当前对象的关联流程,比如看到以这个单下推的后续节点,以及跟这个单关联的上游;对于上游还做了什么其他业务是会被屏蔽调的; 如上图案例:采购订单推了入库单给库存模块的业务员,推了应付单给另一个模块的业务员; 本质上库存模块的业务员是不能关注应付单的信息(避免越权之类的场景) 目前系统上就是这么设计的; 【案例】目前仅二开实现在采购入库单,全流程跟踪能够查看应付单 实现方案:在采购入库单中,打开采购订单的全流程跟踪图; 核心逻辑 <1>找到需要打开流程图的源单内码和源单标识 <2>打开流程图 ```csharp using Kingdee.BOS; using Kingdee.BOS.Business.Bill.Operation; using Kingdee.BOS.BusinessEntity.BillTrack; using Kingdee.BOS.BusinessEntity.BusinessFlow; using Kingdee.BOS.Core; using Kingdee.BOS.Core.Bill.PlugIn; using Kingdee.BOS.Core.BusinessFlow.ServiceArgs; using Kingdee.BOS.Core.DynamicForm; using Kingdee.BOS.Core.DynamicForm.PlugIn.Args; using Kingdee.BOS.Core.Metadata; using Kingdee.BOS.Core.Metadata.EntityElement; using Kingdee.BOS.Core.SqlBuilder; using Kingdee.BOS.Orm.DataEntity; using Kingdee.BOS.ServiceHelper; using Kingdee.BOS.Util; using System; using System.Collections.Generic; using System.Linq; namespace Tmp.BusinessFlow.Tool.Operation { [Kingdee.BOS.Util.HotUpdate] public class TrackAllWithSpecBill : AbstractBillPlugIn { /* * 根据当前操作的单据内码,找到目标单的单据内码 */ public Context Context { get { return this.View.Context; } } /// <summary> /// 重写查看流程图事件 /// </summary> /// <returns></returns> public override void BarItemClick(BarItemClickEventArgs e) { if(!e.BarItemKey.EqualsIgnoreCase("tb_ShowSpecBillTrack")) { return; } /* * 根据当前单据内码,切换到目标 * <1>直接源单,根据link直接获取 * <2>跨级源单,通过下推携带到目标单;或者通过加载全流程实例获取 * https://vip.kingdee.com/article/71661049120113152?productLineId=1 * 演示 单据界面,根据link获取上有单据加载源单内码 */ if (this.View == null || this.View.Model.DataObject == null) return; var billBusinessInfo = this.View.BillBusinessInfo; DynamicObject billObj = this.View.Model.DataObject; //<1>根据link计算源单内码和源单标识 if(billBusinessInfo.GetForm().LinkSet.LinkEntitys== null || billBusinessInfo.GetForm().LinkSet.LinkEntitys.Count <=0) { return; } var linkSetEntity = this.View.BillBusinessInfo.GetForm().LinkSet.LinkEntitys[0]; var linkEntity = billBusinessInfo.GetEntity(linkSetEntity.Key); var entity = billBusinessInfo.GetEntity(linkSetEntity.ParentEntityKey); List<DynamicObject> entityObjs = new List<DynamicObject>(); if(entity is HeadEntity) { entityObjs.Add(billObj); } else if(entity is EntryEntity) { DynamicObjectCollection entityObjColl = billObj[entity.EntryName] as DynamicObjectCollection; if (entityObjColl == null) return; foreach(var entityRowObj in entityObjColl) { entityObjs.Add(entityRowObj); } } if (entityObjs.Count <= 0) return; string stableId = null; List<long> billIds = new List<long>(); foreach(var entityRow in entityObjs) { DynamicObjectCollection linkObjColl = entityRow[linkEntity.EntryName] as DynamicObjectCollection; if (linkObjColl == null || linkObjColl.Count <= 0) continue; foreach(var linkRow in linkObjColl) { string sTableName = linkRow["STableName"].ToString(); if(stableId != null && sTableName != stableId) { continue; } stableId = sTableName; long sBillId = ObjectUtils.Object2Int64(linkRow["SBillId"]); billIds.Add(sBillId); } } //static TableDefine LoadTableDefine(Context ctx, string tableNumber) var td = BusinessFlowServiceHelper.LoadTableDefine(this.View.Context, stableId); string formId = td.FormId; //<2>显示业务流程图 var viewParameter = GetBillFlows(formId, billIds); if (viewParameter == null || viewParameter.Instances.Count == 0) { return; } this.ShowBusinessFlow(viewParameter); } /// <summary> /// 计算流程图 /// </summary> /// <param name="formId"></param> /// <param name="billIds"></param> /// <returns></returns> private ViewBusinessFlowParameter GetBillFlows(string formId, List<long> billIds) { if (formId == null || billIds == null || billIds.Count <= 0) { return null; } //目标单元数据 FormMetadata metaData = MetaDataServiceHelper.Load(this.Context, formId) as FormMetadata; TrackAllHelper helper = new TrackAllHelper(this.Context, metaData.BusinessInfo); var result = helper.LoadBillView(billIds); return result; } private void ShowBusinessFlow(ViewBusinessFlowParameter viewParameter) { // 交换区数据 this.View.Session[FormConst.ConvParamKey_ViewBusinessFlowParameter] = viewParameter; this.View.Session["FormOperation"] = null; DynamicFormShowParameter param = new DynamicFormShowParameter(); param.FormId = FormIdConst.BOS_TrackResultForm; param.ParentPageId = this.View.PageId; param.OpenStyle.ShowType = TrackHelper.GetShowType(this.View); this.View.ShowForm(param); } } /// <summary> /// 全流程跟踪帮助类 /// 把此抽出来作为公有方法,供移动,和全流程跟踪刷新使用 /// </summary> public class TrackAllHelper { private BusinessInfo BillBusinessInfo; private Context Context; public TrackAllHelper(Context ctx, BusinessInfo businessInfo) { Context = ctx; BillBusinessInfo = businessInfo; } /// <summary> /// 加载单据内码关联的所有分录内码 /// </summary> /// <param name="billIds"></param> /// <returns></returns> private Dictionary<string, List<Tuple<long, long>>> LoadBillIds(List<long> billIds) { billIds = billIds.Distinct().ToList(); Dictionary<string, List<Tuple<long, long>>> allEntityIds = new Dictionary<string, List<Tuple<long, long>>>(); //记录实体 单据头内码 List<Tuple<long, long>> billIdTuples = new List<Tuple<long, long>>(); foreach (var billId in billIds) { billIdTuples.Add(new Tuple<long, long>(billId, billId)); } Entity headEntity = BillBusinessInfo.Entrys.FirstOrDefault((entity) => entity is HeadEntity); allEntityIds.Add(headEntity.Key.ToUpperInvariant(), billIdTuples); var pkArray = billIds.Select(x => (object)x).ToArray(); DynamicObject[] billObjs = BusinessDataServiceHelper.Load(Context, pkArray, BillBusinessInfo.GetDynamicObjectType()); if (billObjs == null || billObjs.Length <= 0) return allEntityIds; //记录实体 单据体内码 foreach (var entity in BillBusinessInfo.Entrys) { //仅支持单据体 if (entity is HeadEntity || entity is SubHeadEntity || entity is SubEntryEntity) continue; string strEntityPropertyName = entity.DynamicProperty.Name; var entryIdTuples = new List<Tuple<long, long>>(); foreach (var billObj in billObjs) { DynamicObjectCollection objCollections = billObj[strEntityPropertyName] as DynamicObjectCollection; if (objCollections == null || objCollections.Count <= 0) continue; foreach (DynamicObject row in objCollections) { object id = row["Id"]; if (id == null) { continue; } long entryId = Convert.ToInt64(id); if (entryId == 0) { continue; } entryIdTuples.Add(new Tuple<long, long>(Convert.ToInt64(billObj["Id"]), entryId)); } } allEntityIds.Add(entity.Key.ToUpperInvariant(), entryIdTuples); } return allEntityIds; } /// <summary> /// 获取Link实体关联的实体 /// </summary> /// <param name="metaData"></param> /// <returns></returns> public static List<Entity> GetLinkEntitys(BusinessInfo billBusinessInfo) { List<Entity> linkEntities = new List<Entity>(); if (billBusinessInfo.GetForm().LinkSet == null || (billBusinessInfo.GetForm().LinkSet.LinkEntitys == null)) return linkEntities; billBusinessInfo.GetForm().LinkSet.LinkEntitys.ForEach(linkEntity => { string linkEntryKey = ""; Entity entity = null; linkEntryKey = linkEntity.ParentEntityKey; entity = billBusinessInfo.GetEntity(linkEntryKey); if (entity != null) { linkEntities.Add(entity); } }); return linkEntities; } /// <summary> /// 加载单据内码关联所有实体的分 /// </summary> /// <param name="billIds"></param> /// <returns></returns> public ViewBusinessFlowParameter LoadBillView(List<long> billIds) { Dictionary<string, List<Tuple<long, long>>> allEntityIds = LoadBillIds(billIds); Entity headEntity = BillBusinessInfo.Entrys.FirstOrDefault((entity) => entity is HeadEntity); ViewBusinessFlowParameter viewParam = new ViewBusinessFlowParameter(); viewParam.BillInfo = new ViewBusinessFlowBillInfo(BillBusinessInfo.GetForm().Id); List<BusinessFlowInstance> instances = this.LoadAllInstances(allEntityIds, headEntity, billIds); if (instances.IsEmpty() == false) { var queryChangeEntityParamValue = SystemParameterServiceHelper.GetParamter(Context, 0, 0, "BF_SystemParameter", "FQueryChangeEntity"); var isEnableCrossEntityQuery = ObjectUtils.Object2Bool(queryChangeEntityParamValue); if (isEnableCrossEntityQuery) { this.ChangeEntityQuery(viewParam, ref instances); } } viewParam.Instances.AddRange(instances); return viewParam; } /// <summary> /// 加载单据全部实体的全部业务流程实例 /// </summary> /// <param name="allEntityIds"></param> /// <param name="headEntity"></param> /// <param name="billIds"></param> /// <param name="billInfo">同步输出本次发起联查的单据体内码</param> /// <returns></returns> private List<BusinessFlowInstance> LoadAllInstances(Dictionary<string, List<Tuple<long, long>>> allEntityIds, Entity headEntity, List<long> billIds, BusinessInfo info = null) { List<BusinessFlowInstance> instances = new List<BusinessFlowInstance>(); string formId = info == null ? BillBusinessInfo.GetForm().Id : info.GetForm().Id; // 逐个单据体寻找其业务流程实例 foreach (var item in allEntityIds) { Entity entity = info == null ? BillBusinessInfo.GetEntity(item.Key) : info.GetEntity(item.Key); List<long> entryIds = new List<long>(); if (this.IsHeadEntity(entity)) { entryIds.AddRange(billIds); } else { item.Value.ForEach((t) => entryIds.Add(t.Item2)); } var entityInstances = this.LoadInstancesByEntryIds(formId, entity.Key, entryIds.ToArray()); var validateInstance = this.RemoveJointlessNodes(formId, entity.Key, entryIds.ToArray(), entityInstances); instances.AddRange(validateInstance); } return instances; } #region 加载并合并流程实例 /// <summary> /// 改为公共方法,使业务流程图也能使用 /// </summary> /// <param name="viewParam"></param> /// <param name="entityInstances"></param> private void ChangeEntityQuery(ViewBusinessFlowParameter viewParam, ref List<BusinessFlowInstance> entityInstances) { if (entityInstances.IsEmpty()) return; var currentInstances = new List<BusinessFlowInstance>(); var reachedInstIds = new HashSet<string>(); var reachedNodes = new HashSet<string>(); var reachedTableName = new HashSet<string>();//搜索过的表名 foreach (var item in entityInstances) { currentInstances.Add(item); } //跨实体查询,实例之间并不存在连接或对应关系,故这里可以根据表单批量处理,而不是逐个处理 while (currentInstances.Count > 0) { //得到需要搜索的节点,按节点表名进行分组 var groupNodesByTbName = new Dictionary<string, List<long>>(); foreach (var instItem in currentInstances) { reachedInstIds.Add(instItem.Id); List<RouteTreeNode> lstNodes = this.GetAllNodes(instItem.FirstNode); //所有的节点 foreach (RouteTreeNode node in lstNodes) { if (node.Id != null && !reachedNodes.Contains(node.Id.CId)) //节点没有搜索过 { List<long> lstId = new List<long>(); if (groupNodesByTbName.ContainsKey(node.Id.Tbl)) { lstId = groupNodesByTbName[node.Id.Tbl]; } else { groupNodesByTbName[node.Id.Tbl] = lstId; } lstId.Add(node.Id.EId); reachedNodes.Add(node.Id.CId); } } } currentInstances.Clear(); //对节点进行搜索 var groupNodesByTbDefine = new Dictionary<TableDefine, List<long>>(); foreach (var currentNode in groupNodesByTbName) { var tbDefine = BusinessFlowServiceHelper.LoadTableDefine(Context, currentNode.Key); groupNodesByTbDefine[tbDefine] = currentNode.Value; reachedTableName.Add(currentNode.Key); } foreach (var currentNode in groupNodesByTbDefine) { var crossInstances = this.GetInstances(currentNode, reachedTableName); //得到跨实体流程 foreach (var itemInst in crossInstances) { if (reachedInstIds.Contains(itemInst.Id)) continue; currentInstances.Add(itemInst); } } //存在跨实体数据则使用根节点作为焦点 if (currentInstances.Count > 0) { viewParam.IsRootForceFormId = true; entityInstances.AddRange(currentInstances); } } } /// <summary> /// 得到所有节点 /// </summary> /// <param name="parentNote"></param> /// <returns></returns> private List<RouteTreeNode> GetAllNodes(RouteTreeNode parentNote, int parentDepth = 0) { List<RouteTreeNode> allNode = new List<RouteTreeNode>(); allNode.Add(parentNote); foreach (var child in parentNote.ChildNodes) { int currDepth = parentDepth; RecursionLimitUtils.Run(ref currDepth, 200, "TrackAllFlows->GetAllNodes"); var childs = this.GetAllNodes(child, currDepth); allNode.AddRange(childs); } return allNode; } /// <summary> /// /// </summary> /// <param name="item"></param> /// <returns></returns> private List<BusinessFlowInstance> GetInstances(KeyValuePair<TableDefine, List<long>> item, HashSet<string> reachedTableName) { //构建实体key和列名集合 var tbDefine = item.Key; var entityKeyAndColumnKey = new Dictionary<string, string>(); var businessInfo = FormMetaDataCache.GetCachedFormMetaData(Context, tbDefine.FormId).BusinessInfo; Entity noteEntity = businessInfo.GetEntity(tbDefine.EntityKey); //节点对应的实体 var tuple = this.GetFilterCondition(businessInfo, noteEntity, item.Value); var pkName = businessInfo.GetForm().PkFieldName; var headTbDefine = BusinessFlowServiceHelper.LoadTableDefine(Context, tbDefine.FormId, businessInfo.Entrys[0].Key, false); if (headTbDefine != null) { if (!reachedTableName.Contains(headTbDefine.TableNumber)) { entityKeyAndColumnKey[businessInfo.Entrys[0].Key] = pkName; //单据头 } } //构建参数 var queryParam = new QueryBuilderParemeter(); queryParam.FormId = businessInfo.GetForm().Id; queryParam.FilterClauseWihtKey = tuple.Item1; queryParam.SelectItems.Add(new SelectorItemInfo(pkName)); foreach (var entry in businessInfo.Entrys) { if (entry is EntryEntity && entry.Key != noteEntity.Key) { var entryTableDefine = BusinessFlowServiceHelper.LoadTableDefine(Context, tbDefine.FormId, entry.Key, false); if (entryTableDefine == null) continue; if (reachedTableName.Contains(entryTableDefine.TableNumber)) continue; var columnKey = string.Format("{0}_{1}", entry.Key, entry.EntryPkFieldName); entityKeyAndColumnKey[entry.Key] = columnKey; queryParam.SelectItems.Add(new SelectorItemInfo(columnKey)); } } List<BusinessFlowInstance> lstInstances = new List<BusinessFlowInstance>(); if (entityKeyAndColumnKey.Count > 0) { //得到查询数据 DynamicObjectCollection objs; if (tuple.Item2 == null) { objs = QueryServiceHelper.GetDynamicObjectCollection(Context, queryParam); } else { objs = QueryServiceHelper.GetDynamicObjectCollection(Context, queryParam, new List<SqlParam>() { tuple.Item2 }); } //构建查询节点数据 var allEntityIds = new Dictionary<string, List<Tuple<long, long>>>(); foreach (var dic in entityKeyAndColumnKey) { var lstTuple = new List<Tuple<long, long>>(); allEntityIds[dic.Key] = lstTuple; foreach (var obj in objs) { var billId = ObjectUtils.Object2Int64(obj[pkName]); var entityId = ObjectUtils.Object2Int64(obj[dic.Value]); if (entityId == 0) continue; var tItem = Tuple.Create<long, long>(billId, entityId); if (!lstTuple.Contains(tItem)) { lstTuple.Add(tItem); } } } var lstBillId = allEntityIds.First().Value.Select(x => x.Item1).ToList(); lstInstances = this.LoadAllInstances(allEntityIds, businessInfo.Entrys[0], lstBillId, businessIn

业务流.全流程跟踪.源单和下游单显示不同的原因和二开方案

【场景】采购订单下推采购入库单,采购订单下推付款申请单采购订单的全流程图![1679457091489.webp](/download/0100d2265faa09cf4711b5eb78...
点击下载文档文档为doc格式

声明:除非特别标注,否则均为本站原创文章,转载时请以链接形式注明文章出处。如若本站内容侵犯了原著者的合法权益,可联系本站删除。

已经是第一篇
确认删除?
回到顶部
客服QQ
  • 客服QQ点击这里给我发消息
QQ群
  • 答案:my7c点击这里加入QQ群
支持邮箱
微信
  • 微信