操作插件自动下推代码
金蝶云社区-卫腾
卫腾
14人赞赏了该文章 6,205次浏览 未经作者许可,禁止转载编辑于2019年03月25日 11:48:20
summary-icon摘要由AI智能服务提供

本文提供了一份基于Kingdee BOS平台的自动下推插件代码示例。该代码通过定义`ZDXT`方法和`DoPush`方法实现了从特定源单据(如库存调拨入库单)自动下推到目标单据(如销售出库单)的功能。代码中使用了Kingdee BOS平台的API,包括数据库操作、服务获取、单据转换规则查询、单据构建与保存等。`ZDXT`方法执行数据库查询,获取源单据数据,并通过`DoPush`方法实现下推逻辑,包括规则匹配、下推参数构建、调用下推服务、生成目标单据数据包及保存目标单据等步骤。此外,还提供了`CheckOpResult`方法用于判断操作结果是否成功,并在失败时抛出相应异常。

近期,我在论坛上看见很多位同仁们在论坛上搜索自动下推插件,我根据论坛上的前辈们的代码整理出一份可用的下推插件代码,仅供参考,不足之处,还望海涵using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.ComponentModel;
using Kingdee.BOS.Core.DynamicForm.PlugIn;
using Kingdee.BOS.App.Data;
using Kingdee.BOS.Core.DynamicForm.PlugIn.Args;
using Kingdee.BOS.Contracts;
using Kingdee.BOS.App;
using Kingdee.BOS;
using Kingdee.BOS.Core.List;
using Kingdee.BOS.Core.Metadata.ConvertElement.ServiceArgs;
using Kingdee.BOS.Core.DynamicForm.Operation;
using Kingdee.BOS.Orm.DataEntity;
using Kingdee.BOS.Orm;
using Kingdee.BOS.Core.DynamicForm;
using Kingdee.BOS.Core.Interaction;
using Kingdee.BOS.Core.Metadata;
using Kingdee.BOS.Util;

public void ZDXT() {
var rows = DBUtils.ExecuteDynamicObject(this.Context, string.Format("select s.FID,s.FENTRYID,r.FQTYRETURNEDGOODSWRITTENOFF2,a.FEXCHANGERATE,r.FBUSINESSTYPES2 from T_RVF_sterilisation r inner join T_STK_STKTRANSFERINENTRY s on r.FTEXT=s.FENTRYID inner join T_STK_STKTRANSFERIN a on a.FID=s.FID where r.FID={0}", Id));
List list = new List();
if (rows.Count > 0) {

for (int i = 0; i < rows.Count; i++) {
list.Add(new canshu() { fid = Convert.ToInt64(rows[i][0]), fentryid = Convert.ToInt64(rows[i][1]), FQTYRETURNEDGOODSWRITTENOFF2 = Convert.ToInt32(rows[i][2]), FEXCHANGERATE = Convert.ToDecimal(rows[i][3]), FBUSINESSTYPES2=Convert.ToString(rows[i][4]) });

}
}

this.DoPush("STK_TransferDirect", "SAL_OUTSTOCK", list);

}

///


/// 自动下推并保存
///

/// 源单FormId
/// 目标单FormId
/// 源单内码
private void DoPush(string sourceFormId, string targetFormId, List sourceBillIds)
{
// 获取源单与目标单的转换规则
IConvertService convertService = ServiceHelper.GetService();
var rules = convertService.GetConvertRules(this.Context, sourceFormId, targetFormId);

if (rules == null || rules.Count == 0)
{
throw new KDBusinessException("", string.Format("未找到{0}到{1}之间,启用的转换规则,无法自动下推!", sourceFormId, targetFormId));
}
// 取勾选了默认选项的规则
var rule = rules.FirstOrDefault(t => t.IsDefault);
// 如果无默认规则,则取第一个
if (rule == null)
{
rule = rules[2];
}

// 开始构建下推参数:
// 待下推的源单数据行
List srcSelectedRows = new List();

foreach (var billId in sourceBillIds)
{// 把待下推的源单内码,逐个创建ListSelectedRow对象,添加到集合中
//srcSelectedRows.Add(new ListSelectedRow(billId.ToString(), string.Empty, 0, sourceFormId));
// 特别说明:上述代码,是整单下推;
// 如果需要指定待下推的单据体行,请参照下句代码,在ListSelectedRow中,指定EntryEntityKey以及EntryId
srcSelectedRows.Add(new ListSelectedRow(billId.fid.ToString(), billId.fentryid.ToString(), 0, sourceFormId) { EntryEntityKey = "FEntity" });

}

// 指定目标单单据类型:情况比较复杂,没有合适的案例做参照,示例代码暂略,直接留空,会下推到默认的单据类型
string targetBillTypeId = string.Empty;
// 指定目标单据主业务组织:情况更加复杂,需要涉及到业务委托关系,缺少合适案例,示例代码暂略
// 建议在转换规则中,配置好主业务组织字段的映射关系:运行时,由系统根据映射关系,自动从上游单据取主业务组织,避免由插件指定
long targetOrgId = 0;
// 自定义参数字典:把一些自定义参数,传递到转换插件中;转换插件再根据这些参数,进行特定处理
Dictionary custParams = new Dictionary();
// 组装下推参数对象
PushArgs pushArgs = new PushArgs(rule, srcSelectedRows.ToArray())
{

TargetBillTypeId = targetBillTypeId,
TargetOrgId = targetOrgId,
CustomParams = custParams

};

// 调用下推服务,生成下游单据数据包
ConvertOperationResult operationResult = convertService.Push(this.Context, pushArgs, OperateOption.Create());
// 开始处理下推结果:
// 获取下推生成的下游单据数据包
DynamicObject[] targetBillObjs = (from p in operationResult.TargetDataEntities select p.DataEntity).ToArray();
if (targetBillObjs.Length == 0)
{
// 未下推成功目标单,抛出错误,中断审核
throw new KDBusinessException("", string.Format("由{0}自动下推{1},没有成功生成数据包,自动下推失败!", sourceFormId, targetFormId));
}

// 对下游单据数据包,进行适当的修订,以避免关键字段为空,自动保存失败
// 示例代码略

// 获取生成的目标单据数据包
DynamicObject[] objs = (from p in operationResult.TargetDataEntities
select p.DataEntity).ToArray();
//MustQty RealQty Lot批号 BaseUnitQty基本单位数量
// ((DynamicObject)((DynamicObjectCollection)((DynamicObject)objs[0])[66])[0])[8] = WeightPlan;
int i = 0;
foreach (var billId in sourceBillIds)
{
((DynamicObject)((DynamicObjectCollection)((DynamicObject)objs[0])["SAL_OUTSTOCKENTRY"])[i])["RealQty"] = Convert.ToInt32(billId.FQTYRETURNEDGOODSWRITTENOFF2);
((DynamicObject)((DynamicObjectCollection)((DynamicObject)objs[0])["SAL_OUTSTOCKENTRY"])[i])["alreadyQty"] = Convert.ToInt32(billId.FQTYRETURNEDGOODSWRITTENOFF2);
((DynamicObject)((DynamicObjectCollection)((DynamicObject)objs[0])["SAL_OUTSTOCKENTRY"])[i])["WaitingQty"] = 0;
(((DynamicObject)objs[0])["FOUTSTOCKTYPE"]) = Convert.ToString(billId.FBUSINESSTYPES2);
if (billId.FEXCHANGERATE > 0)
{
((DynamicObject)((DynamicObjectCollection)((DynamicObject)objs[0])["SAL_OUTSTOCKFIN"])[0])["ExchangeRate"] = Convert.ToInt32(billId.FEXCHANGERATE);
}
else {

((DynamicObject)((DynamicObjectCollection)((DynamicObject)objs[0])["SAL_OUTSTOCKFIN"])[0])["ExchangeRate"] = 1.0;
}

i++;

}

// 读取目标单据元数据
IMetaDataService metaService = ServiceHelper.GetService();
var targetBillMeta = metaService.Load(this.Context, targetFormId) as FormMetadata;

// 构建保存操作参数:设置操作选项值,忽略交互提示
OperateOption saveOption = OperateOption.Create();

// 忽略全部需要交互性质的提示,直接保存;
saveOption.SetIgnoreWarning(true); // 忽略交互提示
saveOption.SetInteractionFlag(this.Option.GetInteractionFlag()); // 如果有交互,传入用户选择的交互结果
// using Kingdee.BOS.Core.Interaction;
saveOption.SetIgnoreInteractionFlag(this.Option.GetIgnoreInteractionFlag());
//// 如下代码,强制要求忽略交互提示(演示案例不需要,注释掉)
//saveOption.SetIgnoreWarning(true);
//// using Kingdee.BOS.Core.Interaction;
//saveOption.SetIgnoreInteractionFlag(true);

// 调用保存服务,自动保存
ISaveService saveService = ServiceHelper.GetService();
var saveResult = saveService.Save(this.Context, targetBillMeta.BusinessInfo, targetBillObjs, saveOption, "Save");
// 判断自动保存结果:只有操作成功,才会继续
if (this.CheckOpResult(saveResult, saveOption))
{
return;
}

}

///


/// 判断操作结果是否成功,如果不成功,则直接抛错中断进程
///

/// 操作结果
/// 操作参数
///
///
private bool CheckOpResult(IOperationResult opResult, OperateOption opOption) {
bool isSuccess = false;
if (opResult.IsSuccess == true)
{
// 操作成功
isSuccess = true;
}
else {
if (opResult.InteractionContext != null && opResult.InteractionContext.Option.GetInteractionFlag().Count > 0)
{
// 有交互性提示
// 传出交互提示完整信息对象
this.OperationResult.InteractionContext = opResult.InteractionContext;
// 传出本次交互的标识,
// 用户在确认继续后,会重新进入操作;
// 将以此标识取本交互是否已经确认过,避免重复交互
this.OperationResult.Sponsor = opResult.Sponsor;
// 抛出交互错误,把交互信息传递给前端
new KDInteractionException(opOption, opResult.Sponsor);

}
else {
// 操作失败,拼接失败原因,然后抛出中断
opResult.MergeValidateErrors();
if (opResult.OperateResult == null)
{// 未知原因导致提交失败
throw new KDBusinessException("", "未知原因导致自动提交、审核失败!");
}
else {

StringBuilder sb = new StringBuilder();
sb.AppendLine("自动操作失败:");
foreach (var operateResult in opResult.OperateResult)
{
sb.AppendLine(operateResult.Message);
}
throw new KDBusinessException("", sb.ToString());
}

}

}
return isSuccess;

}