直接调拨单上有很多字段都存在调入方和调出方2套字段,比如调出物料和调入物料分别对应统一物料编
码在调出组织下和调入组织下的数据和内码,但是如果是直接调拨单作为单据转换的目标单据就有些麻
烦,因为BOS只会处理使用组织是主业务组织也就是调出方的基础资料的组织映射取数,如果把调出方的
基础资料直接赋值给调入方字段,在报表统计时就会出现数据问题,需要把基础资料转换为调入组织下
的数据赋值过去才行,这个过程需要编写单据转换插件来处理,如下代码可做参考
using Kingdee.BOS.Contracts;
using Kingdee.BOS.Core;
using Kingdee.BOS.Core.Metadata.ConvertElement.PlugIn;
using Kingdee.BOS.Core.Metadata.FieldElement;
using Kingdee.BOS.Core.SqlBuilder;
using Kingdee.BOS.Orm.DataEntity;
using Kingdee.BOS.Util;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
namespace "请自行修改名称空间"
{
[Description("目标单是直接调拨单单据转换插件:处理调入方物料、BOM、批号等")]
public class ConvertToTransferDirectPlugIn : AbstractConvertPlugIn
{
public override void OnCreateLink (Kingdee.BOS.Core.Metadata.ConvertElement.PlugIn.Args.CreateLinkEventArgs e)
{
//目标单不是直接调拨单不处理
if (!e.TargetBusinessInfo.GetForm().Id.EqualsIgnoreCase("STK_TransferDirect"))
{
return;
}
var dataObjs = e.TargetExtendedDataEntities.FindByEntityKey("FBillHead");
Dictionary<string, DynamicObject> materials = new Dictionary<string, DynamicObject>();
BaseDataField destMatField = e.TargetBusinessInfo.GetField("FDestMaterialID") as BaseDataField;
BaseDataField destLotField = e.TargetBusinessInfo.GetField("FDestLot") as BaseDataField;
IViewService service = Kingdee.BOS.Contracts.ServiceFactory.GetService<IViewService>(this.Context);
Dictionary<string, DynamicObject> boms = new Dictionary<string, DynamicObject> ();
BaseDataField destBomField = e.TargetBusinessInfo.GetField("FDestBomId") as BaseDataField;
//循环目标单实体数据处理
foreach (var obj in dataObjs)
{
DynamicObjectCollection entrys = obj.DataEntity["TransferDirectEntry"] as DynamicObjectCollection;
long stockInOrgId = Convert.ToInt64(obj.DataEntity["StockOrgId_Id"]);
List<long> matMasterIds = new List<long>();
List<long> bomMasterIds = new List<long>();
foreach (DynamicObject entry in entrys)
{
//获取调出物料,
DynamicObject material = entry["MaterialID"] as DynamicObject;
if (material != null)
{
long matmsterid = Convert.ToInt64(material[FormConst.MASTER_ID]);
string key = string.Format("{0}_{1}", stockInOrgId, matmsterid);
if (!matMasterIds.Contains(matmsterid) && !materials.ContainsKey (key))
{
matMasterIds.Add(matmsterid);
}
}
//取出调出BOM
DynamicObject bom = entry["BomId"] as DynamicObject;
if (bom != null)
{
long bommsterid = Convert.ToInt64(bom[FormConst.MASTER_ID]);
string key = string.Format("{0}_{1}", stockInOrgId, bommsterid);
if (!matMasterIds.Contains(bommsterid) && !boms.ContainsKey(key))
{
bomMasterIds.Add(bommsterid);
}
}
}
//批量加载物料
//可改为其他更高效的过滤条件
if (matMasterIds.Count > 0)
{
QueryBuilderParemeter para = new QueryBuilderParemeter();
para.FormId = destMatField.LookUpObject.FormId;
para.IsShowApproved = true;
para.IsShowUsed = true;
para.FilterClauseWihtKey = string.Format(" FUSEORGID = {0} AND FMASTERID IN ({1}) ", stockInOrgId, string.Join(",", matMasterIds));
DynamicObject[] mats = service.Load(this.Context, destMatField.RefFormDynamicObjectType, para);
foreach (DynamicObject mat in mats)
{
string key = string.Format("{0}_{1}", stockInOrgId, mat[FormConst.MASTER_ID]);
if (!materials.ContainsKey(key))
{
materials[key] = mat;
}
}
}
//批量加载BOM
//可改为其他更高效的过滤条件
if (bomMasterIds.Count > 0)
{
QueryBuilderParemeter para = new QueryBuilderParemeter();
para.FormId = destBomField.LookUpObject.FormId;
para.IsShowApproved = true;
para.IsShowUsed = true;
para.FilterClauseWihtKey = string.Format(" FUSEORGID = {0} AND FMASTERID IN ({1}) ", stockInOrgId, string.Join(",", bomMasterIds));
DynamicObject[] destBoms = service.Load(this.Context, destMatField.RefFormDynamicObjectType, para);
foreach (DynamicObject dybom in destBoms)
{
string key = string.Format("{0}_{1}", stockInOrgId, dybom[FormConst.MASTER_ID]);
if (!boms.ContainsKey(key))
{
boms[key] = dybom;
}
}
}
foreach (DynamicObject entry in entrys)
{
//获取调出物料
DynamicObject material = entry["MaterialID"] as DynamicObject;
if (material == null)
{
continue;
}
//获取批号捡货后得到调出批号
DynamicObject lot = entry["Lot"] as DynamicObject;
string lotText = Convert.ToString(entry["Lot_text"]);
//设置调入物料
long materialmasterId = (long)(material[FormConst.MASTER_ID]);
material = null;
string key = string.Format("{0}_{1}", stockInOrgId, materialmasterId);
materials.TryGetValue(key, out material);
if (material != null)
{
SetBaseDataValue(service, entry, destMatField, (long)material["Id"], ref material);
if (material == null)
{
continue;
}
//如果物料没有启用BOM,清空调入BOM
DynamicObjectCollection ptys = ((DynamicObjectCollection)material["MaterialInvPty"]);
DynamicObject pty = ptys.SingleOrDefault(p => Convert.ToInt64(p["InvPtyId_Id"]) == 10003 && Convert.ToBoolean(p["IsEnable"]));
if (pty == null)
{
entry["DESTBOMID"] = null;
entry["DESTBOMID_Id"] = 0;
}
else
{
//BOM内码转换
DynamicObject bom = entry["BomId"] as DynamicObject;
if (bom != null)
{
long bommsterid = Convert.ToInt64(bom[FormConst.MASTER_ID]);
key = string.Format("{0}_{1}", stockInOrgId, bommsterid);
DynamicObject destBom = null;
boms.TryGetValue(key, out destBom);
if (destBom != null)
{
SetBaseDataValue(service, entry, destBomField, (long)destBom["Id"], ref destBom);
}
else
{
entry["DESTBOMID"] = null;
entry["DESTBOMID_Id"] = 0;
}
}
}
//如果物料没有启用批号,清空调入批号
bool isbatchManage = Convert.ToBoolean(((DynamicObject)((DynamicObjectCollection)material["MaterialStock"])[0])["IsBatchManage"]);
if (!isbatchManage || lot == null)
{
entry["DestLot"] = null;
entry["DestLot_Id"] = 0;
entry["DestLot_text"] = "";
}
}
}
}
}
#region 给基础资料字段赋值
/// <summary>
/// 给基础资料字段赋值
/// </summary>
private void SetBaseDataValue(IViewService service, DynamicObject data,
BaseDataField bdfield, long value, ref DynamicObject dyValue)
{
if (value == 0)
{
bdfield.RefIDDynamicProperty.SetValue(data, 0);
bdfield.DynamicProperty.SetValue(data, null);
dyValue = null;
}
else
{
if (dyValue == null)
{
dyValue = service.LoadSingle(this.Context, value, bdfield.RefFormDynamicObjectType);
}
if (dyValue != null)
{
bdfield.RefIDDynamicProperty.SetValue(data, value);
bdfield.DynamicProperty.SetValue(data, dyValue);
}
else
{
bdfield.RefIDDynamicProperty.SetValue(data, 0);
bdfield.DynamicProperty.SetValue(data, null);
}
}
}
#endregion
}
}
声明:
1、以上代码未经测试,仅供编写参考
2、保险起见可以再限定一下源单类型,避免被误用
3、也可以根据需要在AfterCreateLink事件中完成转换处理
4、分步式调出单和分步式调入单类似,但是需要注意字段名的差异
推荐阅读