电脑桌面
添加蚂蚁七词文库到电脑桌面
安装后可以在桌面快捷访问

单据转换插件手册

来源:金蝶云社区作者:金蝶2024-09-239

单据转换插件手册

# 单据转换插件手册 ## 1.场景 单据转换,能够把A单据的数据,根据转换规则,转换生成B单据,单据转换过程中,会触发单据转换插件事件,允许自定义插件进行干预。 ## 2.适用版本 金蝶云苍穹 4.0.004以上 ## 3.单据转换步骤 - 读取源单到目标单之间的全部转换规则; - 匹配转换规则的业务范围,确定适用于当前所选源单的转换规则; - 提取转换规则上,字段映射页签及其他页签,使用到的源单字段; - 根据源单内码,生成源单取数条件; - 读取源单数据行: - 只读取转换规则用到的源单字段; - 如果源单是整单下推,则读取源单全部行;否则取源单所选行数据; - 把单据头、单据体字段组合在一起,生成拉平后的源单数据行; - 根据转换规则,数据范围的配置,对源单行数据,进行筛选,剔除不符合条件的行; - 根据分单、分录行合并策略,对源单数据行进行分组; - 根据分组后的源单数据行,生成目标单、目标单分录行; - 逐行填写目标分录行、单据头字段值; - 在目标单的关联子实体中,记录来源单据信息; - 后续保存目标单时,会根据关联子实体中的来源单据信息,记录单据关联关系及反写; - 如果没有在关联子实体中记录来源单据,则不记录单据关联关系,不能联查,也不能反写; - 输出生成好的目标单数据包,完成单据转换 - 特别说明:单据转换,只是生成目标单数据包,并没有保存入库; ## 4.单据转换插件各事件的触发时机及用途 ### 4.1.插件接口及基类 1. #### 单据转换插件接口 ```java package kd.bos.entity.botp.plugin; public interface IConvertPlugIn { /** * 单据转换可选参数 * @return */ default OperateOption getOption() { return OperateOption.create(); } default void setOption(OperateOption option) {} /** * 开始执行转换规则之前,创建规则上挂的插件后,触发此事件 * * @param opType * @param srcMainType * @param tgtMainType * @param rule * @remark * 由 CreateConvertPlugAction 动作触发 */ void setContext(ConvertOpType opType, BillEntityType srcMainType, BillEntityType tgtMainType, ConvertRuleElement rule); // 代码顺序:按单据转换操作,各种执行场景,各场景中执行的活动进行排序; // 阅读时,按照顺序,从上到下寻找适合的事件 // 各转换操作公共事件 * /** * 初始化变量事件,此时还没有开始编译规则 * * @param e * @remark * 获取上下文信息,构建一些必须的变量 * 由 InitializeAction 动作触发 */ default void initVariable(InitVariableEventArgs e){} /** * 编译数据筛选条件前事件:可追加定制条件,是否忽略规则原生的条件 * * @param e 事件参数:包括本次下推的源单数据、是否忽略规则原生条件 * @remark * 由 ConvertRuleCompiler 动作触发 */ default void beforeBuildRowCondition(BeforeBuildRowConditionEventArgs e){} /** * 构建分单、行合并模式之前事件:调整分单、合并策略及依赖的字段 * * @param e * @remark * 由 ConvertRuleCompiler 动作触发 */ default void beforeBuildGroupMode(BeforeBuildGroupModeEventArgs e){} /** * 构建取数参数后事件:可在正式读取源单数据之前,添加额外的字段、过滤条件 * * @param e * @remark * 由 BuildQueryParameterAction 动作触发 */ default void afterBuildQueryParemeter(AfterBuildQueryParemeterEventArgs e){} /** * 取源单数据前事件:可在正式读取源单数据之前,修改取数语句、取数条件 * * @param e * @remark * 由 LoadSourceDataAction 动作触发 */ default void beforeGetSourceData(BeforeGetSourceDataEventArgs e){} /** * 取源单数据后事件:根据源单数据,获取其他定制的引用数据;也可以替换系统自动获取到的数据 * * @param e * @remark * 由 RunDataConditionAction 动作触发 */ default void afterGetSourceData(AfterGetSourceDataEventArgs e){} /** * 初始化创建目标单据数据包前事件 (暂未触发) * * @param e * @remark * 这个事件,只在选单时触发: * 选单时,需要基于现有的目标单数据包,进行追加处理; * 插件可以在此事件,获取到现有的目标单数据包,提前进行定制处理 */ default void beforeCreateTarget(BeforeCreateTargetEventArgs e){} /** * 创建目标单据数据包后事件:把根据分单规则创建好的目标单,传递给插件 * * @param e * @remark * 由 CreateLinkEntityRowsAction 动作触发 */ default void afterCreateTarget(AfterCreateTargetEventArgs e){} /** * 目标字段赋值完毕后事件:插件可以在此基础上,继续填写目标字段值 * * @param e * @remark * 由 MappingFieldAction 动作触发 */ default void afterFieldMapping(AfterFieldMappingEventArgs e){} /** * 记录关联关系前事件:取消记录关联关系 * * @param e * @remark * 由 FillLinkInfoAction 动作触发 */ default void beforeCreateLink(BeforeCreateLinkEventArgs e){} /** * 记录关联关系后事件:根据系统自动记录的关联关系,进行相关数据的同步携带,如携带其他子单据体数据 * * @param e * @remark * 由 FillLinkInfoAction 动作触发 */ default void afterCreateLink(AfterCreateLinkEventArgs e){} /** * 单据转换后事件,最后执行:插件可以在这个事件中,对生成的目标单数据,进行最后的修改 * * @param e * @remark * 由 MergePushResultAction 动作触发 */ default void afterConvert(AfterConvertEventArgs e){} // 选单前事件 * /** * 选单条件生成后,触发此事件:供插件追加选单条件 * * @param e */ default void afterBuildDrawFilter(AfterBuildDrawFilterEventArgs e) {} } ``` 2. #### 单据转换插件基类`AbstractConvertPlugIn`,实现了转换插件接口`IConvertPlugin` ```java public class AbstractConvertPlugIn implements IConvertPlugIn { } ``` 3. #### 创建并注册插件 自定义单据转换插件,必须扩展插件基类AbstractConvertPlugIn,绑定到单据转换规则上: ![631017735f6a4f000198ae4a.webp](/download/0100e31d1f5ca69b412891896446015087df.webp) 4. #### 附:自定义单据转换插件示例 ```java package kd.bos.plugin.sample.bill.billconvert.bizcase; import kd.bos.entity.BillEntityType; import kd.bos.entity.botp.ConvertOpType; import kd.bos.entity.botp.ConvertRuleElement; import kd.bos.entity.botp.plugin.AbstractConvertPlugIn; import kd.bos.entity.botp.plugin.args.AfterBuildQueryParemeterEventArgs; import kd.bos.entity.botp.plugin.args.AfterConvertEventArgs; import kd.bos.entity.botp.plugin.args.AfterCreateLinkEventArgs; import kd.bos.entity.botp.plugin.args.AfterCreateTargetEventArgs; import kd.bos.entity.botp.plugin.args.AfterFieldMappingEventArgs; import kd.bos.entity.botp.plugin.args.AfterGetSourceDataEventArgs; import kd.bos.entity.botp.plugin.args.BeforeBuildGroupModeEventArgs; import kd.bos.entity.botp.plugin.args.BeforeBuildRowConditionEventArgs; import kd.bos.entity.botp.plugin.args.BeforeCreateLinkEventArgs; import kd.bos.entity.botp.plugin.args.BeforeCreateTargetEventArgs; import kd.bos.entity.botp.plugin.args.BeforeGetSourceDataEventArgs; import kd.bos.entity.botp.plugin.args.InitVariableEventArgs; /** * 演示单据转换插件事件的触发时机 * * @author rd_JohnnyDing * */ public class BillConvertEventSample extends AbstractConvertPlugIn { /** * 演示如何获取上下文信息 */ private void getContext(){ // 源单主实体 BillEntityType srcMainType = this.getSrcMainType(); // 目标单主实体 BillEntityType tgtMainType = this.getTgtMainType(); // 转换规则 ConvertRuleElement rule = this.getRule(); // 转换方式:下推、选单 ConvertOpType opType = this.getOpType(); } /** * 初始化变量事件 * * @param e * @remark * 获取上下文信息,构建一些必须的变量 */ @Override public void initVariable(InitVariableEventArgs e) { this.printEventInfo("initVariable", ""); } /** * 构建取数参数后事件 * * @param e * @remark * 添加额外的字段、过滤条件 */ @Override public void afterBuildQueryParemeter(AfterBuildQueryParemeterEventArgs e) { this.printEventInfo("afterBuildQueryParemeter", ""); } /** * 编译数据筛选条件前事件 * * @param e * @remark * 设置忽略规则原生的条件,改用插件定制条件,或者在规则条件基础上,追加定制条件 * */ @Override public void beforeBuildRowCondition(BeforeBuildRowConditionEventArgs e) { this.printEventInfo("beforeBuildRowCondition", ""); } /** * 取源单数据前事件 * * @param e * @remark * 修改取数语句、取数条件 */ @Override public void beforeGetSourceData(BeforeGetSourceDataEventArgs e) { this.printEventInfo("beforeGetSourceData", ""); } /** * 取源单数据后事件 * * @param e * @remark * 根据源单数据,获取其他定制的引用数据;也可以替换系统自动获取到的数据 */ @Override public void afterGetSourceData(AfterGetSourceDataEventArgs e) { this.printEventInfo("afterGetSourceData", ""); } /** * 构建分单、行合并模式之前事件 * * @param e * @remark * 调整分单、合并策略及依赖的字段 */ @Override public void beforeBuildGroupMode(BeforeBuildGroupModeEventArgs e) { this.printEventInfo("beforeBuildGroupMode", ""); } /** * 初始化创建目标单据数据包前事件 * * @param e * @remark * 这个事件,只在选单时触发: * 选单时,需要基于现有的目标单数据包,进行追加处理; * 插件可以在此事件,获取到现有的目标单数据包,提前进行定制处理 */ @Override public void beforeCreateTarget(BeforeCreateTargetEventArgs e) { this.printEventInfo("beforeCreateTarget", ""); } /** * 创建目标单据数据包后事件 * * @param e * @remark * 这个事件,只在下推时触发,把根据分单规则创建好的目标单,传递给插件 */ @Override public void afterCreateTarget(AfterCreateTargetEventArgs e) { this.printEventInfo("afterCreateTarget", ""); } /** * 目标字段赋值完毕后事件 * * @param e * @remark * 插件可以在此基础上,继续填写目标字段值 */ @Override public void afterFieldMapping(AfterFieldMappingEventArgs e) { this.printEventInfo("afterFieldMapping", ""); } /** * 记录关联关系前事件 * * @param e * @remark * 取消记录关联关系 */ @Override public void beforeCreateLink(BeforeCreateLinkEventArgs e) { this.printEventInfo("beforeCreateLink", ""); } /** * 记录关联关系后事件 * * @param e * @remark * 根据系统自动记录的关联关系,进行相关数据的同步携带,如携带其他子单据体数据 */ @Override public void afterCreateLink(AfterCreateLinkEventArgs e) { this.printEventInfo("afterCreateLink", ""); } /** * 单据转换后事件,最后执行 * * @param e * @remark * 插件可以在这个事件中,对生成的目标单数据,进行最后的修改 */ @Override public void afterConvert(AfterConvertEventArgs e) { this.printEventInfo("afterConvert", ""); } private void printEventInfo(String eventName, String argString){ String msg = String.format("%s : %s", eventName, argString); System.out.println(msg); } } ``` ### 4.2.插件事件 单据转换插件,提供如下插件事件: | 事件 | 触发时机 | | ------------------------ | ---------------------------- | | initVariable | 初始化变量事件 | | afterBuildQueryParemeter | 构建取数参数后事件 | | beforeBuildRowCondition | 编译数据筛选条件前事件 | | beforeGetSourceData | 取源单数据前事件 | | afterGetSourceData | 取源单数据后事件 | | beforeBuildGroupMode | 构建分单、行合并模式之前事件 | | beforeCreateTarget | 暂未触发 | | afterCreateTarget | 创建目标单据数据包后事件 | | afterFieldMapping | 目标字段赋值完毕后事件 | | beforeCreateLink | 记录关联关系前事件 | | afterCreateLink | 记录关联关系后事件 | | afterConvert | 单据转换完毕事件,最后执行 | 1. #### initVariable 事件 - 事件触发时机 - 开始运行转换规则,创建好了转换规则上绑定的单据转换插件之后,即触发此事件。插件可以在此事件中,对本地变量进行初始化。 - 此事件发生时,源单主实体、目标单主实体、转换规则都已经确定,可以基于这些上下文信息,初始化本地变量。 - 一些通用的单据转换业务插件,需要自动适应各种单据,这个事件就显得比较重要: - 可以在转换规则执行前,让通用插件了解到当前的上下文,初始化一些变量,决定后续业务逻辑。 - 插件可以利用如下方法,获取到源单、目标单主实体、反写规则: ```java private void getContext(){ // 源单主实体 BillEntityType srcMainType = this.getSrcMainType(); // 目标单主实体 BillEntityType tgtMainType = this.getTgtMainType(); // 转换规则 ConvertRuleElement rule = this.getRule(); // 转换方式:下推、选单 ConvertOpType opType = this.getOpType(); } ``` - 代码模板 ```java package kd.bos.plugin.sample.bill.billconvert.template; import kd.bos.entity.botp.plugin.AbstractConvertPlugIn; import kd.bos.entity.botp.plugin.args.InitVariableEventArgs; public class InitVariable extends AbstractConvertPlugIn { @Override public void initVariable(InitVariableEventArgs e) { // TODO 在此添加业务逻辑 } } ``` - 示例 - 案例说明 1. 需要开发一个通用单据转换插件,把目标单单据体上的金额字段值,合计到单据头上; 2. 不同的单据上,单据体、单据头上的金额字段标识不同; 3. 暂时只支持采购费用发票、销售费用发票; - 实现方案 1. 捕获 `initVariable`事件,确认源单、目标单,单据体、单据头各金额字段标识; 2. 在`afterCreateLink`事件,根据单据体金额字段,合计单据头金额字段,并换算本位币金额; - 实例代码 ```java package kd.bos.plugin.sample.bill.billconvert.bizcase; import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; import java.util.Date; import kd.bos.dataentity.entity.DynamicObject; import kd.bos.dataentity.entity.DynamicObjectCollection; import kd.bos.dataentity.utils.StringUtils; import kd.bos.entity.ExtendedDataEntity; import kd.bos.entity.botp.plugin.AbstractConvertPlugIn; import kd.bos.entity.botp.plugin.args.AfterCreateLinkEventArgs; import kd.bos.entity.botp.plugin.args.InitVariableEventArgs; public class InitVariableSample extends AbstractConvertPlugIn { / 目标单主实体标识 */ private String targetEntityNumber; / 目标单单据体标识 */ private String key_entryentity; private boolean isOtherBill = false; / 字段标识,单据头.价税合计_原币*/ private String key_AllAmountOri; / 字段标识,单据体.价税合计_原币*/ private String key_AllAmountOri_D; / 字段标识,单据头.价税合计_本位币*/ private String key_AllAmount; / 字段标识,单据头.不含税金额_原币*/ private String key_AmountOri; / 字段标识,单据体.不含税金额_原币*/ private String key_AmountOri_D; / 字段标识,单据头.不含税金额_本位币*/ private String key_Amount; / 字段标识,单据头.税额_原币*/ private String key_TaxAmountOri; / 字段标识,单据体.税额_原币*/ private String key_TaxAmountOri_D; / 字段标识,单据头.税额_本位币*/ private String key_TaxAmount; /** * 初始化事件:根据目标单,确定价税合计金额等字段标识 */ @Override public void initVariable(InitVariableEventArgs e) { this.targetEntityNumber = this.getTgtMainType().getName(); this.setAmountKey(); } /** * 关联关系已经记录,并重算了反写控制字段值之后,触发此事件 * * @remark * 金额字段,是反写控制字段: * 反写控制字段,需要记录从每条源单行携带过来的值,然后自动合计到单据体字段上; * 用户手工修改单据体上的反写控制字段时,会根据原始携带量分配、反写到源单 * * 因此,如果要依赖于反写控制字段值进行运算,必须在afterCreateLink事件之后 * */ @Override public void afterCreateLink(AfterCreateLinkEventArgs e) { if (this.isOtherBill){ // 其他未知的单据,不合计金额 return; } ExtendedDataEntity[] billDataEntitys = e.getTargetExtDataEntitySet().FindByEntityKey(this.targetEntityNumber); // 逐单合计单据头金额字段值 for(ExtendedDataEntity billDataEntity : billDataEntitys){ this.calcAmount(billDataEntity); } } /** * 根据目标单,设置含税价格等字段标识 */ private void setAmountKey() { if (StringUtils.equals(this.targetEntityNumber, "iv_purexpinv")){ // 采购费用发票 this.key_entryentity = "entryentity"; //价税合计 this.key_AllAmountOri = "amountori"; this.key_AllAmountOri_D = "amountori"; this.key_AllAmount = "amount"; //不含税金额 this.key_AmountOri = "headauxpriceori"; this.key_AmountOri_D = "headauxpriceori"; this.key_Amount = "headauxprice"; //税额 this.key_TaxAmountOri = "deductibletaxori"; this.key_TaxAmountOri_D = "deductibletaxori"; this.key_TaxAmount = "deductibletax"; } else if (StringUtils.equals(this.targetEntityNumber, "iv_saleexpinv")){ // 销售费用发票 this.key_entryentity = "entryentity"; //价税合计 this.key_AllAmountOri = "aftertotaltaxfor"; this.key_AllAmountOri_D = "allamountori"; this.key_AllAmount = "aftertotaltax"; //不含税金额 this.key_AmountOri = "headauxpriceori"; this.key_AmountOri_D = "amountori"; this.key_Amount = "headauxprice"; //税额 this.key_TaxAmountOri = "taxamount"; this.key_TaxAmountOri_D = "detailtaxamountori"; this.key_TaxAmount = "taxamountori"; } else { // 其他单据:不在此插件中计算价税合计 isOtherBill = true; } } /** * 计算价税合计 * * @param billDataEntity */ private void calcAmount(ExtendedDataEntity billDataEntity){ long currencyID = (long) billDataEntity.getValue("currencyid_id"); // 原币 long mainCurrencyID =(long) billDataEntity.getValue("mainbookstdcurrid_id"); // 本币 long exchangeTypeID = (long) billDataEntity.getValue("exchangetype_id"); // 换算类型 Date date = (Date) billDataEntity.getValue("date"); // 业务日期 // 取当日汇率 BigDecimal rate = new BigDecimal("0"); if (currencyID > 0 && mainCurrencyID > 0) { rate = this.getExchangeBusRate(currencyID, mainCurrencyID, exchangeTypeID, date); } // 把汇率回填到单据上 billDataEntity.setValue("exchangerate", rate); // 开始合计金额:逐行循环,汇总到变量上 BigDecimal taxAmountOriH = new BigDecimal("0"); // 单据头.税额 BigDecimal noTaxAmountOriH = new BigDecimal("0"); // 单据头.不含税金额 BigDecimal totalTaxAmountOriH = new BigDecimal("0"); //单据头.价税合计 DynamicObjectCollection entryRows = (DynamicObjectCollection)billDataEntity.getValue(this.key_entryentity); for (DynamicObject entryRow : entryRows){ taxAmountOriH = taxAmountOriH.add(entryRow.getBigDecimal(key_TaxAmountOri_D)); // 原币 单据体.税额 noTaxAmountOriH = noTaxAmountOriH.add(entryRow.getBigDecimal(key_AmountOri_D)); // 原币 单据体.不含税金额 totalTaxAmountOriH = totalTaxAmountOriH.add(entryRow.getBigDecimal(key_AllAmountOri_D)); // 原币 单据体.价税合计 } // 填写单据头.原币各金额 billDataEntity.setValue(key_TaxAmountOri, taxAmountOriH); billDataEntity.setValue(key_AmountOri, noTaxAmountOriH); billDataEntity.setValue(key_AllAmountOri, totalTaxAmountOriH); // 本位币各金额 :原币金额 * 汇率 (四舍五入,10位小数) MathContext mc = new MathContext(10, RoundingMode.HALF_UP); billDataEntity.setValue(key_TaxAmount, taxAmountOriH.multiply(rate, mc)); billDataEntity.setValue(key_Amount, noTaxAmountOriH.multiply(rate, mc)); billDataEntity.setValue(key_AllAmount, totalTaxAmountOriH.multiply(rate, mc)); } /** * 取当日汇率 * @return */ private BigDecimal getExchangeBusRate(long currencyId1, long currencyId2, long exchangeType, Date date){ // 略过取汇率的逻辑,直接返回 1 return new BigDecimal("1"); } } ``` 2. #### afterBuildQueryParemeter 事件 - 事件触发时机 - 系统根据转换规则上的字段映射关系,确认好了需要加载的源单字段之后,触发此事件,并传入需转换的源单行过滤条件`( FID in [1,2,3,4] )`。 - 插件可以在此事件中,增加需要加载的源单字段,调整源单行取数条件。 - 代码模板 ```java package kd.bos.plugin.sample.bill.billconvert.template; import kd.bos.entity.botp.plugin.AbstractConvertPlugIn; import kd.bos.entity.botp.plugin.args.AfterBuildQueryParemeterEventArgs; public class AfterBuildQueryParemeter extends AbstractConvertPlugIn { @Override public void afterBuildQueryParemeter(AfterBuildQueryParemeterEventArgs e) { // TODO 在此添加业务逻辑 } } ``` - 事件参数 ```java public class AfterBuildQueryParemeterEventArgs extends ConvertPluginEventArgs{ /** *预计会加载的源单字段及其别名; */ public Map <String, String> getSrcFldAlias(); /** *添加插件需要用到的源单字段; *传入字段标识,如textfield; *如果要取源单基础资料字段的引用属性,要传入基础资料字段标识及其引用属性,如basedatafield.name; *不需要在前面带单据体标识; */ public void addSrcField(String fullPropName); /** *系统根据传入的源单内码,生成的源单取数条件,插件可以调整此集合中的条件对象; */ public List <QFilter> getQFilters(); } ``` - 示例 - 案例说明 1. 源单有单据编号、业务日期、金额字段 2. 需要把这三个字段值,拼成一个字符串,填写到目标单内容字段上; 3. 业务日期格式化为`yyyy-MM-dd`,金额带币别 - 实现方案 1. 捕获 `afterBuildQueryParemeter` 事件,要求加载源单单据编号、业务日期、金额、币别字段 2. 捕获 `afterFieldMapping` 事件,取源单字段值,格式化后填写在目标单上 - 实例代码 ```java package kd.bos.plugin.sample.bill.billconvert.bizcase; import java.math.BigDecimal; import java.text.SimpleDateFormat; import java.util.Date; import java.util.List; import kd.bos.dataentity.entity.DynamicObject; import kd.bos.entity.ExtendedDataEntity; import kd.bos.entity.botp.plugin.AbstractConvertPlugIn; import kd.bos.entity.botp.plugin.args.AfterBuildQueryParemeterEventArgs; import kd.bos.entity.botp.plugin.args.AfterFieldMappingEventArgs; import kd.bos.entity.botp.runtime.ConvertConst; public class AfterBuildQueryParemeterSample extends AbstractConvertPlugIn { private final static String KEY_BILLNO = "billno"; private final static String KEY_DATE = "date"; private final static String KEY_AMOUNT = "amount"; private final static String KEY_CURRENCYNAME = "currency.name"; private final static String KEY_CONTENT = "content"; /** * 在开始读取源单数据前,触发此事件 * @remark * 在此事件中,要求加载插件要用到的源单字段 */ @Override public void afterBuildQueryParemeter(AfterBuildQueryParemeterEventArgs e) { e.addSrcField(KEY_BILLNO); // 单据编号 e.addSrcField(KEY_DATE); // 业务日期 e.addSrcField(KEY_AMOUNT); // 金额 e.addSrcField(KEY_CURRENCYNAME); // 币别.名称 currency.name } /** * 目标单字段值,携带完毕后,触发此事件 * @remark * 在此事件中,自行取源单字段值,格式化后填写到目标单 */ @SuppressWarnings("unchecked") @Override public void afterFieldMapping(AfterFieldMappingEventArgs e) { // 取目标单,单据头数据包 (可能会生成多张单,是个数组) String targetEntityNumber = this.getTgtMainType().getName(); ExtendedDataEntity[] billDataEntitys = e.getTargetExtDataEntitySet().FindByEntityKey(targetEntityNumber); SimpleDateFormat timesdf = new SimpleDateFormat("yyyy-MM-dd"); // 逐单处理 for(ExtendedDataEntity billDataEntity : billDataEntitys){ // 取当前目标单,对应的源单行

单据转换插件手册

# 单据转换插件手册## 1.场景单据转换,能够把A单据的数据,根据转换规则,转换生成B单据,单据转换过程中,会触发单据转换插件事件,允...
点击下载文档文档为doc格式

声明:除非特别标注,否则均为本站原创文章,转载时请以链接形式注明文章出处。如若本站内容侵犯了原著者的合法权益,可联系本站删除。

确认删除?
回到顶部
客服QQ
  • 客服QQ点击这里给我发消息
QQ群
  • 答案:my7c点击这里加入QQ群
支持邮箱
微信
  • 微信