本文简要介绍了在K/3 Cloud BOS系统中实现“第三方下推”功能的应用场景和示例代码。第三方下推指的是在单据A(表面上的源单)上点击下推时,实际由单据B(真实源单)下推生成单据C(真实目标单)的过程。示例代码展示了在采购订单列表中使用插件实现JDA(自定义单据)下推到JDB(另一自定义单据)的过程,并包含了下推、选单、下查和上查等操作的实现细节。
实际业务中,常常需要在单据A列表(表面上的源单)上,点击下推时,实际要由单据B(真实源单)下推生成单据C(真实目标单),此需求K/3 Cloud BOS称之为第三方下推。
典型的应用场景,如生产订单(表面上的源单)下推生产领料单,实际上是由生产用料清单(真实源单)下推生产领料单(真实目标单);
如下示例代码,以采购订单单据维护插件为例,演示第三方下推JDB(实际由JDA下推到JDB);以及第三方上查(实际由采购申请上查生产订单):
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.Core;
using Kingdee.BOS.Core.DynamicForm;
using Kingdee.BOS.Core.DynamicForm.PlugIn.Args;
using Kingdee.BOS.Core.Bill.PlugIn;
using Kingdee.BOS.Core.Bill.PlugIn.Args;
using Kingdee.BOS.Core.List;
using Kingdee.BOS.Core.List.PlugIn.Args;
using Kingdee.BOS.Core.Metadata.ConvertElement;
using Kingdee.BOS.BusinessEntity.BillTrack;
namespace JDSample.FormPlugIn.Bill
{
/// <summary>
/// 演示利用插件实现第三方下推
/// </summary>
/// <remarks>
/// 第三方下推:在单据A列表(表面上的源单)上,点击下推,实际是要用单据B(真实源单)下推生成单据C(真实目标单);
/// 关键点:
/// 1. 要在单据A的下推界面上,添加单据C;
/// 2. 要自行根据单据A的内码,找到单据B的内码,以此替换掉下推参数中的源单内码集合;
/// 3. 要在单据A的下查界面,添加单据C;(要在单据C的上查界面,添加单据A);
/// 4. 要在单据A下查界面,找到单据B的内码,然后找到单据C的内码,据此构建出单据C列表过滤条件;
///
/// 本示例代码,要实现:
/// 1. 在采购订单列表下推,实现自定义单据JDA到JDB的下推
/// 2. 在采购订单列表下查,实现下查到JDB的数据
/// </remarks>
[Description("演示利用插件实现第三方下推")]
public class ThirdPushEdit : AbstractBillPlugIn
{
/// <summary>
/// JDA单据的FormId
/// </summary>
private const string JDAFormId = "0964b538-feea-46df-8e48-c7a78b6ca992";
/// <summary>
/// JDB单据的FormId
/// </summary>
private const string JDBFormId = "7f0e9b0e-915b-4b8d-84af-d175685ca1f6";
/// <summary>
/// 点击下推、上下查菜单之后,显示下推界面、联查界面之前触发
/// </summary>
/// <param name="e"></param>
/// <remarks>
/// 可以利用此事件,为下推界面添加目标单据
/// </remarks>
public override void OnShowConvertOpForm(ShowConvertOpFormEventArgs e)
{
base.OnShowConvertOpForm(e);
if (e.ConvertOperation == FormOperationEnum.Push)
{// 下推
// 把 采购订单 -> JDB,替换为 JDA -> JDB
this.DoPush(e);
}
else if (e.ConvertOperation == FormOperationEnum.Draw)
{// 选单
// 选单,把采购订单选采购申请单,替换为采购订单选生产订单
this.DoDraw(e);
}
else if (e.ConvertOperation == FormOperationEnum.TrackDown)
{// 下查
// 采购订单 (表面上的源单) -> JDA (真实源单) -> JDB (真实目标单)
this.DoTrackDown(e);
}
else if (e.ConvertOperation == FormOperationEnum.TrackUp)
{// 上查
// 采购订单 (真实目标单) -> 采购申请单 (真实源单) -> 生产订单 (表面上的源单)
this.DoTrackUp(e);
}
}
/// <summary>
/// 在下推界面,确定好目标单,点击确定,开始下推后触发
/// </summary>
/// <param name="e"></param>
/// <remarks>
/// 可以利用此事件,调整源单内码;
///
/// 本演示代码,本事件仅用于下推,
/// 把采购订单的内码,替换为真实源单JDA单据内码
/// </remarks>
public override void OnGetConvertRule(GetConvertRuleEventArgs e)
{
base.OnGetConvertRule(e);
if (e.ConvertOperation == FormOperationEnum.Push
&& e.TargetFormId.EqualsIgnoreCase(JDBFormId))
{// 用户选择下推到JDB,采用的是第三方下推,需要把源单内码调整为JDA的内码
// 根据实际业务关系,由当前选择的采购订单找到关联的JDA单据
// 演示代码并没有这种关系,略过,直接填写具体的JDA单据内码
List<ListSelectedRow> JDARows = new List<ListSelectedRow>();
JDARows.Add(new ListSelectedRow("100019", "100019", 0, JDAFormId));
// 把源单内码替换为JDA的内码
e.SelectedRows = JDARows.ToArray();
}
}
/// <summary>
/// 联查界面,用户点击关联单据之后,触发本事件
/// </summary>
/// <param name="e"></param>
/// <remarks>
/// 可以利用此事件,调整关联单据内码,以控制关联单据列表的显示内容
///
/// 本演示代码,本事件仅用于上查,
/// 把真实源单采购申请单,替换为表面上的生产订单内码
/// </remarks>
public override void OnShowTrackResult(ShowTrackResultEventArgs e)
{
base.OnShowTrackResult(e);
if (e.TrackOperation == FormOperationEnum.TrackUp)
{// 上查
if (e.TargetFormKey.EqualsIgnoreCase("PRD_MO"))
{// 需要上查生产订单
// e.TrackResult 中存储了真实源单的信息,需要替换为表面上源单
// TODO: 根据e.TrackResult中的真实源单,寻找对应的表面上的源单
// 本演示代码,忽略上述寻找过程,直接替换为生产订单单据体内码100003
BillNode trackResult = BillNode.Create("PRD_MO", "", null);
trackResult.AddLinkCopyData(new List<string>() { "100003" });
// 替换源单内码:由真实源单(采购申请单),替换为表面上的源单(生产订单)
e.TrackResult = trackResult;
// 替换之后,系统将显示上面指定的生产订单单据体行
}
}
}
/// <summary>
/// 把 采购订单 -> JDB,替换为 JDA -> JDB
/// </summary>
/// <param name="e"></param>
private void DoPush(ShowConvertOpFormEventArgs e)
{
// 把真实目标单(JDB),添加到可选下游单据列表
ConvertBillElement JDBInfo = new ConvertBillElement();
JDBInfo.FormID = JDBFormId;
JDBInfo.Name = new LocaleValue("JD单据转换B");
e.BillList.Add(JDBInfo);
// 标记目标单(JDB)为第三方下推,其真实源单为JDA
// 下推操作,ReplaceRelation构造参数说明:
// ReplaceRelation(真实源单FormId, 真实目标单FormId);
ReplaceRelation JDAToJDB = new ReplaceRelation(JDAFormId, JDBFormId);
e.ReplaceRelations.Add(JDAToJDB);
}
/// <summary>
/// 选单,把采购订单选采购申请单,替换为采购订单选生产订单
/// </summary>
/// <param name="e"></param>
private void DoDraw(ShowConvertOpFormEventArgs e)
{
}
/// <summary>
/// 在采购订单上查生产订单,实际上由采购订单 (真实目标单) -> 采购申请单 (真实源单) -> 生产订单 (表面上的源单)
/// </summary>
/// <param name="e"></param>
private void DoTrackUp(ShowConvertOpFormEventArgs e)
{
if (e.ConvertOperation == FormOperationEnum.TrackUp)
{// 上查
// 在上游单据列表中,增加生产订单:供用户双击查询生产订单
ConvertBillElement PRD_MOInfo = new ConvertBillElement();
PRD_MOInfo.FormID = "PRD_MO";
PRD_MOInfo .Name = new LocaleValue("生产订单");
e.BillList.Add(PRD_MOInfo );
// 因为本单与生产订单并没有直接关系,需要借助真实源单(采购申请单)搭一个桥
// 上查操作ReplaceRelation参数说明:
// e.AddReplaceRelation(真实源单FormId(采购申请), 表面上的源单FormId(生产订单));
// 用户双击生产订单时,系统会先找到真实的源单(采购申请)单,
// 然后插件在OnShowTrackResult事件中,替换源单
e.AddReplaceRelation("PUR_Requisition", "PRD_MO");
}
}
/// <summary>
/// 在采购订单上下查JDB,实际上由采购订单 (表面上的源单) -> JDA (真实源单) -> JDB (真实目标单)
/// </summary>
/// <param name="e"></param>
private void DoTrackDown(ShowConvertOpFormEventArgs e)
{
// 把真实目标单(JDB),添加到可选下游单据列表
ConvertBillElement JDBInfo = new ConvertBillElement();
JDBInfo.FormID = JDBFormId;
JDBInfo.Name = new LocaleValue("JD单据转换B");
e.BillList.Add(JDBInfo);
// 标记目标单(JDB)为第三方下推,其真实源单为JDA
// 下推、选单操作,ReplaceRelation构造参数说明:ReplaceRelation(真实源单FormId, 真实目标单FormId);
// 上查操作,ReplaceRelation构造参数说明:ReplaceRelation(真实源单FormId, 表面上的源单FormId);
// 下查操作,ReplaceRelation构造参数说明:ReplaceRelation(真实源单FormId, 正式目标单FormId);
ReplaceRelation JDAToJDB = new ReplaceRelation(JDAFormId, JDBFormId);
// 当前采购订单分录内码
JDAToJDB.TargetLinkId = new List<string>();
JDAToJDB.TargetLinkId.Add("100047"); // 100047仅用于演示,实际运行时,需要取e.SelectedRows中的单据体内码
// 对应的JDA单据体内码,联查时,将以此内码作为源单内码,搜索JDA下推的JDB单据
JDAToJDB.SourceLinkId = new List<string>();
JDAToJDB.SourceLinkId.Add("100017"); // 100017仅用于演示,实际运行时,需根据关系自行查找第三方源单的内码
e.ReplaceRelations.Add(JDAToJDB);
}
}
}
推荐阅读