# 单据转换插件 — IronPython

源：[金蝶python插件示例/Python单据转换插件示例.txt](../../../../../金蝶python插件示例/Python单据转换插件示例/Python单据转换插件示例.txt)

```python
#引入clr运行库
import clr
#添加对cloud插件开发的常用组件的引用
clr.AddReference('System')
clr.AddReference('System.Data')
clr.AddReference('Kingdee.BOS')
clr.AddReference('Kingdee.BOS.Core')
clr.AddReference('Kingdee.BOS.App')
clr.AddReference('Kingdee.BOS.Contracts')
clr.AddReference('Kingdee.BOS.DataEntity')
clr.AddReference('Kingdee.BOS.BusinessEntity')
clr.AddReference('Kingdee.BOS.ServiceHelper')
#导入cloud基础库中的常用实体对象（分命名空间导入，不会递归导入）
from Kingdee.BOS import *
from Kingdee.BOS.Core import *
from Kingdee.BOS.Core.Bill import *
from Kingdee.BOS.Orm.DataEntity import *
from Kingdee.BOS.Contracts import *
from Kingdee.BOS.App import *
from Kingdee.BOS.Core.DynamicForm.PlugIn import *
from Kingdee.BOS.Core.DynamicForm.PlugIn.ControlModel import *
from Kingdee.BOS.Core.Metadata import *
from Kingdee.BOS.Core.Metadata.ConvertElement.PlugIn import*
from Kingdee.BOS.Core.Metadata.ConvertElement.PlugIn.Args import*
from System import *
from System.Data import *
from System.Text import *
from System.Collections import *
from Kingdee.BOS.App.Data import *
from System.Collections.Generic import List
from Kingdee.BOS.ServiceHelper import *
from Kingdee.BOS.Util import*

#解析字段映射关系，并构建查询参数。
#这里可以加入你想要的额外的字段
def OnQueryBuilderParemeter(e):
	#插件常用全局属性，顺带介绍一下，不一定在此事件中使用***********************************************************************
	#this.OperationNumber;#操作编码，如下推，选单操作等，值分别为Push,Draw,
	#paraDIC=this.Option.GetVariables();#获取自定义参数集，字典类型,例如是否整单下推、是否需要校验下游单据新增权限、WebAPI调下推时传入的自定义参数等等
	#if(paraDIC.ContainsKey("参数标识")==True):#判断是否含有某个参数
	#	paraValue=paraDIC["参数标识"];#取出参数标识
	#***********************************************************************************************************************
	#e.SourceBusinessInfo;#上游单据的元数据信息，可从这里获取一些上游单据的关键信息
	# secFormId=e.SourceBusinessInfo.GetForm().Id;#上游单据FormId
	 billNo=SelectorItemInfo("FBillNo");#加入单据转化规则中没有配置的，但需要额外加载的字段
	 e.SelectItems.Add(billNo);

#解析过滤策略中配置的条件,可以在这里加自定义的下推过滤条件
#此事件开始前，刚完成选单条件策略中的过滤条件的解析
#e.FilterPolicySQL来自于：【选单条件策略中设置的过滤条件(JsonSetting)】+【选单条件策略中的附加条件(CustFilter)】+【按目标组织基础资料属性过滤的条件(TargetOrgBDFilterList)】
#此事件结束后，e.FilterPolicySQL将使用AND操作符合并到QueryBuilderParemeter.FilterClauseWihtKey，后续作用于选单列表取数
def OnParseFilter(e):
	filterStr=" FBillNo LIKE 'CGSQ%' "; 
	e.FilterPolicySQL=StringUtils.JoinFilterString(e.FilterPolicySQL,filterStr);#追加过滤条件,默认用AND连接
	e.PlugFilterDesc = "单据编号必须包含【CGSQ】";#过滤条件描述信息，下推不满足时，会提示出来。

#选单时才有,解析字段映射关系中配置的过滤选项:过滤/仅追加
#此事件开始前，刚完成用于选单列表取数的QueryBuilderParemeter的构建，e.FilterOptionsSQL来自于QueryBuilderParemeter.FilterClauseWihtKey
def OnParseFilterOptions(e):
	#e.TargetData;#目标单的数据包
	#e.SourceBusinessInfo;#源单元数据信息
	#e.TargetBusinessInfo;#目标单元数据信息
	filterStr=" FReqQty > 10 ";
	e.FilterOptionsSQL = StringUtils.JoinFilterString(e.FilterOptionsSQL,filterStr);#追加选单过滤条件

#获取到源单数据之后触发,(下推执行)
#可以在此事件中修改源单下推的数据包，不会真实修改源单，只会影响下推的携带值
#例如,可以动态修改源单分单依据字段的值，以此实现动态分单策略
def OnGetSourceData(e):
	#e.SourceBusinessInfo;#源单元数据信息
	srcData=e.SourceData;#源单数据，本次下推的所有数据行,DynamicObjectCollection类型
	#可循环从数据包集合中取数，只能取到参与转换规则中配置的字段和OnQueryBuilderParemeter额外加入的字段
	for row in srcData:
		srcId=row["Id"];#源单Id
		srcEntryId=str(dr["FEntity_FEntryID"]);#源单分录内码:单据体标识_FEntryId

#获取到源单数据之后触发，(选单执行)
#与OnGetSourceData类似，只不过一个是在下推执行，一个是选单执行
def OnGetDrawSourceData(e):
	#e.SourceBusinessInfo;#源单元数据信息
	srcData=e.SourceData;#源单数据，本次下推的所有数据行,DynamicObjectCollection类型
	#可循环从数据包集合中取数，只能取到参与转换规则中配置的字段和OnQueryBuilderParemeter额外加入的字段
	for row in srcData:
		srcId=row["Id"];#源单Id
		srcEntryId=str(dr["FEntity_FEntryID"]);#源单分录内码:单据体标识_FEntryId

#执行分组前触发，可以在此增加自定义的分组字段
def OnBeforeGroupBy(e):
	srcData= e.SourceData;#源单数据
	HeadGroupKey = e.HeadGroupKey;#分单依据
	e.HeadGroupKey =("{0},{1}").format(e.HeadGroupKey,"FXXX");#追加分组字段
	EntryGroupKey=e.EntryGroupKey;#单据体分组合并字段
	e.EntryGroupKey =("{0},{1}").format(e.EntryGroupKey,"FEXXX");#追加单据体分组合并字段
	SubEntryGroupKey=e.SubEntryGroupKey;#子单据体分组字段
	e.SubEntryGroupKey =("{0},{1}").format(e.SubEntryGroupKey,"FEXXX");#追加单据体分组字段

#下推执行，根据分组策略创建目标单,此时还没根据字段映射赋值目标单的字段,这个事件用得不多
#也没有创建关联数据包，接近一个"空白"的下游单据，当然有默认值的字段还是有值
def OnCreateTarget(e):
	headEntity=e.TargetExtendedDataEntities.FindByEntityKey("FBillHead");#分组之后创建的所有目标单集合
	for entity in headEntity:
		billObj=entity.DataEntity;#下游单据的完整数据包,可以通过实体数据包操作方式处理下游单据字段

#选单执行，与OnCreateTarget类似，此时获取到了选单返回的数据，但是还没赋值到下游单据的字段上
def OnCreateDrawTarget(e):
	headEntity=e.TargetExtendedDataEntities.FindByEntityKey("FBillHead");#获取根据分组创建好的目标单

#目标单赋值之前触发,主要用启动字段赋值事件OnFieldMapping,用于监听字段映射赋值过程，用得很少
def OnBeforeFieldMapping(e):
	e.FireFieldMappingEvent=True;#启动字段赋值
	
#字段赋值事件,每个数据包，每个字段都会触发，易影响性能,慎用！
def OnFieldMapping(e):
	headEntity=e.TargetExtendedDataEntities.FindByEntityKey("FBillHead");#下游单据数据集
	fldKey=e.TargetField.Key.ToUpperInvariant();#赋值字段标识大写

#字段映射所有字段赋值完成之后触发，用得很少	
def OnAfterFieldMapping(e):
	headEntity=e.TargetExtendedDataEntities.FindByEntityKey("FBillHead");#下游单据数据集

#创建关联关系之前触发,可以取消创建,用得很少
def OnCreateLink(e):
	headEntity=e.TargetExtendedDataEntities.FindByEntityKey("FBillHead");#下游单据数据集
	#e.Cancel=True;#取消创建

#单据关联关系创建之后触发，表单服务策略执行之前
#如果需要干预下游单据，再执行表单服务策略，可以在此事件中对下游单据进行处理
#例如，要通过插件修改采购订单单价，之后系统自动执行表单服务策略计算金额
def OnAfterCreateLink(e):
	headEntity = e.Result.FindByEntityKey("FBillHead");#由于可能分单，所以可能有多个下游单据，是一个集合
	for entity in headEntity:#循环处理
		billObj=entity.DataEntity;#下游单据的完整数据包,可以通过实体数据包操作方式处理下游单据字段

#获取到服务策略之前触发，可在此事件中加入自定义的表单服务或者移除服务,用得少
def OnGetConvertBusinessService(e):
	FormSvcList=e.FormBusinessServices;#表单服务集合
	
#单据转换执行完成之后执行,在表单服务策略执行完成之后
#可以获取到下推完成之后，还未保存的下游单据，对下游单据数据包做最后的处理
#应用案例：单据转换插件提示消息
def AfterConvert(e):
	#整个单据转换执行完毕后的下游单据数据集合,相当于用户看到的推出来的下游单据,但是还没保存
	headEntity = e.Result.FindByEntityKey("FBillHead");#由于可能分单，所以可能有多个下游单据，是一个集合
	for entity in headEntity:#循环处理
		billObj=entity.DataEntity;
```
