付款申请单,如何追查跨级源头采购订单

来源:互联网 发布:淮南市大数据 编辑:程序博客网 时间:2024/04/29 11:56
案例背景:
采购订单 -> 收料通知单 -> 采购入库单 -> 应付单 -> 付款申请单,采购订单经过多步下推,才生成付款申请单。

现在需要根据付款申请单的单据内码,寻找其源头的采购订单;
打开采购订单列表,展示出来搜索出的源头采购订单;

技术难点:
1. 经过了多步骤下推,如何从付款申请单逐层往上追溯,找到源头采购订单?
2. 如果获取这样的追溯关系?
3. 中间环节应付单,对采购物料明细进行合并,重新归纳了付款计划,在此情景下如何追溯?

实现方案:
1. 通过付款申请单的关联主实体 - 付款明细,根据业务流程实例数据,寻找到源头的应付单
2. 通过应付单的的关联主实体 - 物料明细,读取业务流程实例数据,寻找到源头的采购订单

案例设计:
在付款申请单上,添加一个菜单:联查采购订单(tbSearchSrcPO);
然后挂上本插件,即可验证效果

示例代码:

已经在本地验证通过,代码较长

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.ComponentModel;using Kingdee.BOS;using Kingdee.BOS.Util;using Kingdee.BOS.BusinessEntity.BusinessFlow;using Kingdee.BOS.Core;using Kingdee.BOS.Core.DynamicForm.PlugIn;using Kingdee.BOS.Core.DynamicForm.PlugIn.Args;using Kingdee.BOS.Core.Bill;using Kingdee.BOS.Core.Bill.PlugIn;using Kingdee.BOS.Core.Bill.PlugIn.Args;using Kingdee.BOS.Core.BusinessFlow.ServiceArgs;using Kingdee.BOS.Core.Metadata;using Kingdee.BOS.Core.Metadata.EntityElement;using Kingdee.BOS.Core.List;using Kingdee.BOS.Core.SqlBuilder;using Kingdee.BOS.ServiceHelper;namespace JDSample.FormPlugIn.Bill{    [Description("搜索付款申请单的源头采购订单")]    public class S151202SearchSrcBillEdit : AbstractBillPlugIn    {        public override void AfterBarItemClick(AfterBarItemClickEventArgs e)        {            if (e.BarItemKey.EqualsIgnoreCase("tbSearchSrcPO"))            {// 搜索源头采购订单                if (this.View.Model.GetPKValue() == null )                {                    this.View.ShowMessage("请先保存单据!");                    return;                }                long payAppBillId = Convert.ToInt64(this.View.Model.GetPKValue());                this.DoSearchSrcPO(payAppBillId);            }        }        /// <summary>        /// 搜索源头采购订单,并显示列表        /// </summary>        /// <param name="payAppBillId">付款申请单单据内码</param>        private void DoSearchSrcPO(long payAppBillId)        {            // 读取付款申请单.明细内码            HashSet<long> payAppEntityIds = this.LoadEntityIds(                "CN_PAYAPPLY", "FPAYAPPLYENTRY", new long[] { payAppBillId });            if (payAppEntityIds.Count == 0)            {                this.View.ShowMessage("付款申请单的明细单据体没有数据,没有源单!");                return;            }                        // 读取付款申请单的业务流程实例            BusinessFlowInstanceCollection payAppInsts = this.LoadBFInstances(                "CN_PAYAPPLY", "FPAYAPPLYENTRY", payAppEntityIds.ToArray());            if (payAppInsts.Count == 0)            {                this.View.ShowMessage("付款申请单的明细单据体是手工创建的,没有源单!");                return;            }            // 取付款申请单源头的应付单.付款计划            HashSet<long> apPlanEntityIds = this.GetSrcEntityIdsByInsts(payAppInsts,                "AP_Payable", "FEntityPlan",                "CN_PAYAPPLY", "FPAYAPPLYENTRY", payAppEntityIds);            if (apPlanEntityIds.Count == 0)            {                this.View.ShowMessage("没有找到源头的应付单,线索中断,不能继续追查采购订单");                return;            }            // 根据应付单.付款计划内码,找到应付单.物料明细内码            HashSet<long> apBillIds = this.LoadBillIds("AP_Payable", "FEntityPlan", apPlanEntityIds.ToArray());            HashSet<long> apDetailIds = this.LoadEntityIds("AP_Payable", "FEntityDetail", apBillIds.ToArray());            // 加载应付单.物料明细的业务流程实例            BusinessFlowInstanceCollection apDetailInsts = this.LoadBFInstances(                "AP_Payable", "FEntityDetail", apDetailIds.ToArray());                        // 取应付单源头的采购订单物料明细内码            HashSet<long> poEntityIds = this.GetSrcEntityIdsByInsts(apDetailInsts,                "PUR_PurchaseOrder", "FPOOrderEntry",                "AP_Payable", "FEntityDetail", apDetailIds);                        if (poEntityIds.Count == 0)            {                this.View.ShowMessage("没有找到源头的采购订单!");                return;            }            // 取源头的采购订单内码            HashSet<long> poBillIds = this.LoadBillIds("PUR_PurchaseOrder", "FPOOrderEntry", poEntityIds.ToArray());            // 显示出搜索出来的采购订单列表            this.ShowPOList(poBillIds.ToArray());        }        /// <summary>        /// 根据单据体内码,读取其单据内码        /// </summary>        /// <param name="formId"></param>        /// <param name="entityKey"></param>        /// <param name="entityIds"></param>        /// <returns></returns>        private HashSet<long> LoadBillIds(string formId, string entityKey, long[] entityIds)        {            HashSet<long> billIds = new HashSet<long>();            if (entityKey.EqualsIgnoreCase("FBillHead"))            {// 需要读取的实体为单据头,直接返回实体内码集合,无需到数据库读取                foreach (var entityId in entityIds)                {                    billIds.Add(entityId);                }            }            else            {                // 读取单据的元数据                FormMetadata meta = MetaDataServiceHelper.Load(this.Context, formId) as FormMetadata;                Entity entity = meta.BusinessInfo.GetEntity(entityKey);                // 构建取数服务参数,仅加载单据内码字段                QueryBuilderParemeter queryParam = new QueryBuilderParemeter();                queryParam.FormId = formId;                queryParam.BusinessInfo = meta.BusinessInfo;                queryParam.SelectItems.Add(new SelectorItemInfo(meta.BusinessInfo.GetForm().PkFieldName));                queryParam.FilterClauseWihtKey = string.Format("{0}_{1} in ({2})",                    entityKey, entity.EntryPkFieldName, string.Join(",", entityIds));                // 读取数据                var rows = QueryServiceHelper.GetDynamicObjectCollection(this.Context, queryParam);                                // 把取到的单据内码返回                foreach(var row in rows)                {                    long billId = Convert.ToInt64(row[0]);                    if (billIds.Contains(billId) == false)                    {                        billIds.Add(billId);                    }                }            }            return billIds;        }        /// <summary>        /// 读取指定单据的实体内码返回        /// </summary>        /// <param name="formId">单据formId</param>        /// <param name="entityKey">实体Key</param>        /// <param name="billIds">单据内码集合</param>        /// <returns></returns>        private HashSet<long> LoadEntityIds(string formId, string entityKey, long[] billIds)        {            HashSet<long> entityIds = new HashSet<long>();            if (entityKey.EqualsIgnoreCase("FBillHead"))            {// 需要读取的实体为单据头,直接返回单据内码集合,无需到数据库读取                foreach (var billId in billIds)                {                    entityIds.Add(billId);                }            }            else            {                // 读取单据的元数据                FormMetadata meta = MetaDataServiceHelper.Load(this.Context, formId) as FormMetadata;                Entity entity = meta.BusinessInfo.GetEntity(entityKey);                // 构建取数服务参数,仅加载实体内码字段                QueryBuilderParemeter queryParam = new QueryBuilderParemeter();                queryParam.FormId = formId;                queryParam.BusinessInfo = meta.BusinessInfo;                queryParam.SelectItems.Add(                    new SelectorItemInfo(string.Format("{0}_{1}", entityKey, entity.EntryPkFieldName)));                queryParam.FilterClauseWihtKey = string.Format("{0} in ({1})",                    meta.BusinessInfo.GetForm().PkFieldName, string.Join(",", billIds));                // 读取数据                var rows = QueryServiceHelper.GetDynamicObjectCollection(this.Context, queryParam);                                // 把取到的实体内码返回                foreach(var row in rows)                {                    entityIds.Add(Convert.ToInt64(row[0]));                }            }            return entityIds;        }        /// <summary>        /// 到业务流程实例中,基于目标单,寻找指定单据类型的源单        /// </summary>        /// <param name="insts">业务流程实例</param>        /// <param name="srcFormId">源单formId</param>        /// <param name="srcEntityKey">源单实体key</param>        /// <param name="targetFormId">目标单formId</param>        /// <param name="targetEntityKey">目标实体key</param>        /// <param name="targetEntityIds">目标单实体内码集合</param>        /// <returns></returns>        private HashSet<long> GetSrcEntityIdsByInsts(BusinessFlowInstanceCollection insts,            string srcFormId, string srcEntityKey,            string targetFormId, string targetEntityKey, HashSet<long> targetEntityIds)        {            HashSet<long> srcEntityIds = new HashSet<long>();            if (insts == null || insts.Count == 0)            {                return srcEntityIds;            }            // 到业务流程实例中,寻找目标单所在的节点            string targetTableNumber = this.LoadTableNumber(targetFormId, targetEntityKey);            List<RouteTreeNode> targetNodes = new List<RouteTreeNode>();            foreach (var inst in insts)            {                var nodes = inst.SerarchTargetFormNodes(targetTableNumber);                foreach(var node in nodes)                {                    long targetEntityId = node.Id.EId;                    if (targetEntityIds.Contains(targetEntityId))                    {                        targetNodes.Add(node);                    }                }            }            // 基于目标单所在的节点,反查指定的源单            string srcTableNumber = this.LoadTableNumber(srcFormId, srcEntityKey);            foreach (var targetNode in targetNodes)            {                // 不断往上追溯,寻找指定类型的源单                RouteTreeNode parentNode = targetNode.ParentNode;                while (parentNode != null)                {                    if (parentNode.Id.Tbl.EqualsIgnoreCase(srcTableNumber))                    {// 此父节点,就是需要的源单类型,取值                        if (srcEntityIds.Contains(parentNode.Id.EId) == false)                        {                            srcEntityIds.Add(parentNode.Id.EId);                        }                    }                    parentNode = parentNode.ParentNode;                }            }            return srcEntityIds;        }        /// <summary>        /// 获取单据关联主实体的业务流程实例:业务流程实例记录了每行单据体的来龙去脉        /// </summary>        /// <param name="formId">单据</param>        /// <param name="entityKey">关联主实体Key</param>        /// <param name="entityIds">关联主实体内码集合</param>        /// <returns></returns>        private BusinessFlowInstanceCollection LoadBFInstances(string formId, string entityKey, long[] entityIds)        {            LoadInstancesByEntityIdArgs args = new LoadInstancesByEntityIdArgs(formId, entityKey, entityIds);            var instances = BusinessFlowDataServiceHelper.LoadInstancesByEntityId(this.Context, args);            return instances;        }        /// <summary>        /// 获取单据体的表格编码        /// </summary>        /// <param name="formId">单据FormId</param>        /// <param name="entityKey">实体Key;如果关联主实体是单据头,请传入FBillHead</param>        /// <returns>新建的数据库,从未保存过此业务单据时,表格编码可能为空</returns>        /// <remarks>        /// 在业务流程跟踪关系中,每个单据的单据体都有一个唯一的表格编码。        /// 默认是单据体的物理表格名。        /// 但在此物料表格被多个单据公用时,会在物理表名后面增加序号以示区分        /// </remarks>        private string LoadTableNumber(string formId, string entityKey)        {            var tableDefine = BusinessFlowServiceHelper.LoadTableDefine(this.Context, formId, entityKey);            if (tableDefine == null)            {                return string.Empty;            }            else            {                return tableDefine.TableNumber;            }        }        /// <summary>        /// 显示采购订单列表        /// </summary>        /// <param name="poBillIds"></param>        private void ShowPOList(long[] poBillIds)        {            ListShowParameter showParam = new ListShowParameter();            showParam.FormId = "PUR_PurchaseOrder";            showParam.ListFilterParameter.Filter =                 string.Format(" FID in ({0}) ", string.Join(",", poBillIds));            this.View.ShowForm(showParam);        }    }}


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 我家的金丝熊浑身都是尿怎么办 一键启动车钥匙丢了怎么办 把爷爷的遗物弄丢了怎么办 如果你娶了一个傻子你怎么办 在国外订机票手机收不到信息怎么办 网上买机票名字写错了怎么办 买机票名字错了一个字怎么办 微店没收到货却显示已收货怎么办? 手机存的照片误删了怎么办 魔兽世界把要用的装备分解了怎么办 邻居家的狗见到我就叫怎么办 我的世界玩的时间长会卡应该怎么办 网易我的世界密码账号都忘了怎么办 我的世界创建世界画面乱码了怎么办 网易我的世界云端存档不够用怎么办 玩刺激战场带耳机声音有延迟怎么办 我的世界手机版狼变色怎么办 我的世界开了光影太阳太刺眼怎么办 我的世界饥饿值掉的慢怎么办 我的世界合装备过于昂贵怎么办 我的世界故事模式屏幕是黑的怎么办 人物只剩下轮廓的图用ps怎么办 两年义务兵考军校分数不够怎么办 大学生兵考上军校后原学籍怎么办 我的世界工业附魔到精准采集怎么办 交换生在台期间遗失通行证怎么办 驾驶证上的号码是士兵证号怎么办 士兵证丢了但是要买飞机票怎么办 君泰保安公司不发工资怎么办 冬天洗棉衣后有一圈白色怎么办 买了一批化肥没有执行标准怎么办 防护栏下面打不了膨胀螺丝怎么办 不知道怀孕照了x射线怎么办 腹部照了x光片照了三次怎么办 像在工厂戴的静电帽弄丢了怎么办 诈骗犯把钱被转到别人账户怎么办 狗狗5个月在家随地大小便怎么办 上课放屁放的快没憋到老是放怎么办 丈夫有外遇并跟小三有一儿子怎么办 借款夫妻双亡借出去的钱怎么办? 橡胶底的劳保鞋开胶了怎么办?