
【场景】单据转换不支持多选基础资料下推;
【案例】通过单据转换插件,实现采购申请单单据体的多选基础资料下推到采购订单的单据体的多选基础资料
[单据头案例](https://vip.kingdee.com/article/324304152484608000?productLineId=1)
<0>多选基础资料的基础资料类型必须一致


<1>单据转换插件实现
```csharp
using Kingdee.BOS.Core.Metadata.ConvertElement.PlugIn;
using Kingdee.BOS.Core.Metadata.ConvertElement.PlugIn.Args;
using Kingdee.BOS.Core.Metadata.EntityElement;
using Kingdee.BOS.Core.Metadata.FieldElement;
using Kingdee.BOS.Util;
using System;
using System.Collections.Generic;
namespace DynamicFormPlugIn.BillConvert
{
[Kingdee.BOS.Util.HotUpdate]
public class ConvertMulBaseInEntityPlugIn : AbstractConvertPlugIn
{
public class KeyConst
{
/// <summary>
/// 源单多选基础资料字段
/// </summary>
public static string SrcFieldKey = "F_BHR_MulBaseKey";
/// <summary>
/// 目标单多选基础资料字段
/// </summary>
public static string TgtFieldKey = "F_BHR_MulBaseKey";
}
public override void AfterConvert(AfterConvertEventArgs e)
{
/*
* <0>数据准备
*/
MulBaseDataField tgtBaseDataField = e.TargetBusinessInfo.GetField(KeyConst.TgtFieldKey) as MulBaseDataField;
MulBaseDataField srcBaseDataField = e.SourceBusinessInfo.GetField(KeyConst.SrcFieldKey) as MulBaseDataField;
if (tgtBaseDataField == null || srcBaseDataField == null)
return;
Func<Kingdee.BOS.Orm.DataEntity.DynamicObject, Kingdee.BOS.Orm.DataEntity.DynamicObject> loadSrcRowObj = (srcRow) =>
{
long pkId = ObjectUtils.Object2Int64(srcRow[e.SourceBusinessInfo.GetForm().PkFieldName]);
Kingdee.BOS.Orm.DataEntity.DynamicObject srcObj = LoadSrcBills(e, pkId);
if (srcObj == null)
return null;
string entryKey = string.Format("{0}_{1}", srcBaseDataField.EntityKey, srcBaseDataField.Entity.EntryPkFieldName);
int entryId = ObjectUtils.Object2Int(srcRow[entryKey]);
Kingdee.BOS.Orm.DataEntity.DynamicObjectCollection entityObjs = srcObj[srcBaseDataField.Entity.EntryName] as Kingdee.BOS.Orm.DataEntity.DynamicObjectCollection;
if (entityObjs == null)
return null;
foreach(var entityRow in entityObjs)
{
if(ObjectUtils.Object2Int(entityRow[0]) == entryId)
{
return entityRow;
}
}
return null;
};
Dictionary<object, Kingdee.BOS.Orm.DataEntity.DynamicObject> baseDataObjCache = new Dictionary<object, Kingdee.BOS.Orm.DataEntity.DynamicObject>();
/*
* <1>根据下游单据的数据包,和源单信息,填入多选基础资料
*/
Entity tgtEntity = tgtBaseDataField.Entity;
var targetEntityObjs = e.Result.FindByEntityKey(tgtEntity.Key);
for (int i = 0, sz = targetEntityObjs.Length; i < sz; ++i)
{
var tgtEntityRow = targetEntityObjs[i];
if (tgtEntityRow.DataEntity == null)
continue;
//获取当前目标行的源单数据集合
var sourceRows = tgtEntityRow["ConvertSource"] as List<Kingdee.BOS.Orm.DataEntity.DynamicObject>;
if (sourceRows == null)
continue;
foreach(var srcRow in sourceRows)
{
var srcRowObj = loadSrcRowObj(srcRow);
if (srcRowObj == null)
continue;
//获取源行的多选基础资料
var srcMulBaseData = srcRowObj[srcBaseDataField.PropertyName] as Kingdee.BOS.Orm.DataEntity.DynamicObjectCollection;
if (srcMulBaseData == null || srcMulBaseData.Count <= 0)
continue;
//构造目标单的多选基础资料
Kingdee.BOS.Orm.DataEntity.DynamicObjectCollection tgtMulBaseData = tgtEntityRow.DataEntity[tgtBaseDataField.RefEntityDynamicProperty] as Kingdee.BOS.Orm.DataEntity.DynamicObjectCollection;
if (tgtMulBaseData == null)
{
tgtMulBaseData = new Kingdee.BOS.Orm.DataEntity.DynamicObjectCollection(tgtBaseDataField.RefEntityDynamicObjectType, tgtEntityRow.DataEntity);
tgtEntityRow.DataEntity[tgtBaseDataField.RefEntityDynamicProperty] = tgtMulBaseData;
}
foreach (var srcBaseData in srcMulBaseData)
{
if (srcBaseData == null)
continue;
/*
* 引用属性不一样,重新加载数据
*/
object srcBaseDataId = ((Kingdee.BOS.Orm.DataEntity.DynamicObject)srcBaseData[srcBaseDataField.PropertyName])[0];
if (!baseDataObjCache.ContainsKey(srcBaseDataId))
{
baseDataObjCache[srcBaseDataId] = Kingdee.BOS.ServiceHelper.BusinessDataServiceHelper.Load(this.Context, new object[] { srcBaseDataId }, tgtBaseDataField.RefFormDynamicObjectType)[0];
}
Kingdee.BOS.Orm.DataEntity.DynamicObject tgtBaseDataObjRow = new Kingdee.BOS.Orm.DataEntity.DynamicObject(tgtBaseDataField.RefEntityDynamicObjectType);
tgtBaseDataObjRow[tgtBaseDataField.RefIDDynamicProperty] = srcBaseDataId;
tgtBaseDataObjRow[tgtBaseDataField.DynamicProperty] = baseDataObjCache[srcBaseDataId];
tgtMulBaseData.Add(tgtBaseDataObjRow);
}
}
}
}
/// <summary>
/// 源单数据包缓存
/// </summary>
private Dictionary<long, Kingdee.BOS.Orm.DataEntity.DynamicObject> billDataCache = new Dictionary<long, Kingdee.BOS.Orm.DataEntity.DynamicObject>();
/// <summary>
/// 获取对应单据内码的数据包
/// </summary>
/// <param name="e"></param>
/// <param name="pkId"></param>
/// <returns></returns>
private Kingdee.BOS.Orm.DataEntity.DynamicObject LoadSrcBills(AfterConvertEventArgs e, long pkId)
{
if(billDataCache.ContainsKey(pkId))
{
return billDataCache[pkId];
}
List<string> loadFields = new List<string>() { KeyConst.SrcFieldKey };
Kingdee.BOS.Core.Metadata.BusinessInfo subBusinessInfo = e.SourceBusinessInfo.GetSubBusinessInfo(loadFields);
List<object> pkIds = new List<object>() { pkId };
var srcBillObjs = Kingdee.BOS.ServiceHelper.BusinessDataServiceHelper.Load(this.Context, pkIds.ToArray(), subBusinessInfo.GetDynamicObjectType());
Kingdee.BOS.Orm.DataEntity.DynamicObject billObj = null;
if(srcBillObjs != null && srcBillObjs.Length >0)
{
billObj = srcBillObjs[0];
}
billDataCache[pkId] = billObj;
return billObj;
}
}
}
```
核心逻辑:根据单据转换的数据包,获取源单单据内码和源单分录内码,而后获取源单对应行的多选基础资料;
后续赋值的逻辑与原逻辑一致
【效果】实现单据体的多选基础资料携带

