计划运算向导携带需求单据字段的办法
金蝶云社区-战斗车
战斗车
0人赞赏了该文章 2,088次浏览 未经作者许可,禁止转载编辑于2017年11月27日 16:30:23

计划运算向导的第一步,很多用户在选了计划方案之后,通常需要选择需求单据。之前收到过一些用户的反馈,在选择需求单据的同时,希望能携带更多在需求单据上的字段,来方便计划员在运算时更全面了解需求单据的信息。
但稍显可惜的是,计划运算选单因为系统标准逻辑较为复杂,并且交互界面来回切换,因此之前并不支持计划运算选单携带自定义字段。
不过,既然这是个合理的需求,就有理由支持。我们在最新补丁中已支持在适当二开的情况下,支持计划运算携带自定义字段。具体是6.X打2017-11-16的补丁PT117877,7.X打2017-11-30的补丁PT118904得到支持。

在此补丁基础上,以下讲述适当的二开都需要做些什么,本贴将拿计划运算选销售订单为示例。

设定计划运算选销售订单需要额外携带销售订单上要货日期,明细备注这两个信息。
首先,需在计划运算向导界面添加用于承接这两个信息的字段:

然后,需要写一个计划运算向导的表单插件并注册到标准插件后面,以下是经过验证OK的插件示例:

插件代码如下,请留意注释部分以帮助理解:
using Kingdee.BOS.Core.DynamicForm.PlugIn.WizardForm;
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 Kingdee.K3.Core.MFG.EntityHelper;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;

namespace Kingdee.K3.MFG.PLN.Business.PlugIn.DynamicForm.WizardForm
{
[Description("计划运算向导测试插件")]
public class MrpCalWizardTest : AbstractWizardFormPlugIn
{
public override void AfterDoOperation(BOS.Core.DynamicForm.PlugIn.Args.AfterDoOperationEventArgs e)
{
base.AfterDoOperation(e);

//操作代码固定是AfterSelectBill,
//using Kingdee.BOS.Util;之后可字符串具备EqualsIgnoreCase扩展方法,表示字符串不区分大小写比较
if (e.Operation.Operation.EqualsIgnoreCase("AfterSelectBill"))
{
GetSOProperty();
}
}

///


/// 获取销售订单相关属性
///

private void GetSOProperty()
{
//获取系统标准逻辑选取的销售订单信息
Entity entity = this.View.BusinessInfo.GetEntity("FEntity");
DynamicObjectCollection entrys = this.View.Model.GetEntityDataObject(entity);

//using Kingdee.K3.Core.MFG.EntityHelper;之后,DynamicObject类型的对象将具备GetDynamicValue("...")扩展方法
List soEIds = entrys.Where(w => w.GetDynamicValue("RelationFormId_Id").EqualsIgnoreCase("SAL_SaleOrder"))
.Select(s => s.GetDynamicValue("RelationEntryId")).Distinct().ToList();
if (soEIds.IsEmpty()) return;

//因为本插件是单据表单插件,按规范不能直接执行SQL,所以用QueryServiceHelper捞取数据,也可以用BusinessDataServiceHelper.Load(...)获取
DynamicObjectCollection soInfos = QueryServiceHelper.GetDynamicObjectCollection(this.Context, new QueryBuilderParemeter()
{
FormId = "SAL_SaleOrder", //销售订单标识
SelectItems = SelectorItemInfo.CreateItems(
"FId", //订单内码
"FSaleOrderEntry_FEntryID As FEntryID", //订单分录内码
"FDeliveryDate", //要货日期
"FEntryNote" //表体备注
),
FilterClauseWihtKey = string.Format(" FSaleOrderEntry_FEntryID IN({0}) ", string.Join(",", soEIds)) //过滤条件
});

//对于获取的销售订单数据构建成字典,以提升后续在循环中查找数据的效率
//这也是性能优化最常用并且效果最好的方式之一:循环外统一获取数据,然后构建成字典,再在循环中查找字典取数使用
Dictionary> soInfoGroups =
soInfos.GroupBy(g => g.GetDynamicValue("FEntryID")).ToDictionary(d => d.Key);
IGrouping soInfoGroup;

//用数据模型对表体赋值,循环表体数据,进行自定义字段赋值
for (int i = 0; i < entrys.Count; i++)
{
string formId = entrys[i].GetDynamicValue("RelationFormId_Id");
[/i] if (!formId.EqualsIgnoreCase("SAL_SaleOrder")) continue;

long relationEntryId = entrys.GetDynamicValue("RelationEntryId");
if (!soInfoGroups.TryGetValue(relationEntryId, out soInfoGroup)) continue;

DynamicObject soInfo = soInfoGroup.First();
this.View.Model.SetValue("FDeliveryDate", soInfo.GetDynamicValue("FDeliveryDate"), i);
this.View.Model.SetValue("FEntryNote", soInfo.GetDynamicValue("FEntryNote"), i);
}

//如果表体数量量极大(几百上千行或以上),且自定义字段不涉及实体服务规则和值更新事件,请用以下方式对自定义字段赋值,本例暂注释
//this.View.Model.BeginIniti();
//foreach (DynamicObject entry in entrys)
//{
// string formId = entry.GetDynamicValue("RelationFormId_Id");
// if (!formId.EqualsIgnoreCase("SAL_SaleOrder")) continue;

// long relationEntryId = entry.GetDynamicValue("RelationEntryId");
// if (!soInfoGroups.TryGetValue(relationEntryId, out soInfoGroup)) continue;

// DynamicObject soInfo = soInfoGroup.First();
// entry["DeliveryDate"] = soInfo.GetDynamicValue("FDeliveryDate");
// entry["Note"] = soInfo.GetDynamicValue("FEntryNote");
//}
//this.View.Model.EndIniti();
//DBServiceHelper.LoadReferenceObject(this.Context, entrys.ToArray(), entity.DynamicObjectType, false);
//this.View.UpdateView("FSaleOrderEntry");
}
}
}

实现效果形如: