Application Development Blog Posts
Learn and share on deeper, cross technology development topics such as integration and connectivity, automation, cloud extensibility, developing at scale, and security.
cancel
Showing results for 
Search instead for 
Did you mean: 
ceeshi
Discoverer
Click here for English Version

1. 需求


有时候我们需要为VF01/VF02/VF03增加自定义选项卡来满足用户需求,并且在这个选项卡上维护一些自定义字段的值,在这份文档中我们以金税发票为例。


2. 症状


发票凭证选项卡没有屏幕增强和用户出口,SAP标准只有业务加载项 (BADI_SD_CUST_HEAD, BADI_SD_CUST_ITEM) 可用,但是这两个业务加载项仅供SAP内部使用。

3. 环境


本文基于SAP ERP 6.0 EHP7 IDES,NetWeaver 7.42,并且在SAP S4/HANA 1511(S4Core 100 SP03), NetWeaver 7.49同步验证。

本文使用的SAP GUI是750 Patch 1。

4. 问题重现


当我们尝试创建BADI_SD_CUST_HEADBADI_SD_CUST_ITEM的业务加载项实施时,会看到错误消息“业务加载项定义BADI_SD_CUST_xxxx仅供SAP内部使用”。



检查业务加载项定义,我们发现这些业务加载项被标记为“SAP内部”,所以我们不能使用这个业务加载项来增加我们自己的数据。


5. 原因和前提


5.1 参考


SAP Note 864944 有详细说明,SAP只打算让这些业务加载项用在单独的SAP行业解决方案中。

5.2 调查分析


本文以发票凭证的抬头选项卡为例,计划增加金税发票号和金税发票生成日期两个字段,并且相关数据应当存储在VBRK的附加结构中。

SE93找到VF03对应的主程序是SAPMV60A (VF01/VF02也是同一个),在资源库浏览器中检查程序SAPMV60A的屏幕,发现屏幕6001/6101可能是相关的。



从所用位置可以看出BADI_SD_CUST_HEAD被用在函数模块GET_HANDLE_SD_CUST_HEAD中,这个函数模块的使用位置有4个命中。



同时我们检查屏幕逻辑流(以6001为例),模块CUST_HEAD_ACTIVATE调用的CUST_HEAD_ACTIVATE中使用到函数模块GET_HANDLE_SD_CUST_HEAD



IF_EX_BADI_SD_CUST_HEAD~ACTIVATE_TAB_PAGE的导航目标我们可以看到SAP标准有一个业务加载项实施CL_IM_WB2_IVGUI_LAYOUT_H,我们可以通过SE19查看WB2_IVGUI_LAYOUT_H





结论就是业务加载项定义BADI_SD_CUST_HEAD的实施WB2_IVGUI_LAYOUT_H是为全球贸易这个行业解决方案实现的,存储在WB2B_CORE这个包中。

照此完整来看,为发票凭证增加自定义选项卡的业务加载项实施正是与屏幕6001和6101有关,既然这个业务加载项不允许我们自己来实施,我们可以尝试在屏幕6001和6101中注入类似的代码来达成目标。

5.3 验证


我们来调试找出所有的关键点。

业务加载项实施WB2_IVGUI_LAYOUT_H中有4个方法,我们为每一个方法设置断点,然后找一个发票凭证用VF02来修改。



当我们转到抬头选项卡,会碰到第一个断点ACTIVATE_TAB_PAGE



当我们转到“全球贸易管理”选项卡,会碰到第二个断点TRANSFER_DATA_TO_SUBSCREEN,这个选项卡就是有业务加载项WB2_IVGUI_LAYOUT_H增强出来的。



当我们输入数据或点击屏幕上的按钮,会碰到第三个断点PASS_FCODE_TO_SUBSCREEN,然后碰到第四个断点TRANSFER_DATA_FROM_SUBSCREEN



使用调试器的“返回 (F7)”我们可以验证这四个断点都是跟屏幕6001和6101有关的,这就验证了之前的结论。

以上是基于SAP ERP 6.0 EHP7 IDES,但是基本上在生产环境我们不会有“全球贸易管理”这个选项卡,让我们来找出根本原因。

检查WB2_IVGUI_LAYOUT_H->ACTIVATE_TAB_PAGE中的代码并追溯,最终找到控制点来自TWGTA-WB2_ADDON_ACTIVE



TWGTA是通过视图V_TWGTA维护的,配置路径是SPRO-->后勤 - 常规-->全球贸易管理-->激活组件,找到配置选项“增强设置”-->“附加激活”。



当这个选项设置为“2 所有凭证激活”,我们可以在发票凭证抬头看到增强的“全球贸易管理”选项卡。



尝试设置成“未激活



这样“全球贸易管理”选项卡就不见了。



这个选项属于“SAP企业扩展全球贸易”这个行业解决方案,包含在独立的EA-GLTRADE组件中,从S4/HANA 1503开始被合并到S4CORE中。



这个选项在不同SAP版本中的默认值不同,具体如下:


6. 解决方案


6.1 副作用


因为SAP只预留了一个屏幕对发票凭证抬头进行增强,所以我们为发票凭证增加我们自定义的选项卡之前需要注意检查“全球贸易管理”的有效性。

如下解决方案基于我们未启用“全球贸易管理”的前提,如果希望启用“全球贸易管理”的情况下增加自定义的数据,可以考虑在业务加载项WB2_IVGUI_LAYOUT_H中处理,本文不再赘述,参考主程序SAPLWB2B_SCREEN_HANDLING

6.2 附加结构


要显示在自定义选项卡中的数据,我们将定义ZZ字段附加到VBRK中,以便这些数据能够自动存储在VBRK里。为了避免冲突,所有的名称应当以两个Z打头,因为有些标准字段的名称是以一个Z打头的。

创建数据元素ZGTINO,描述、数据类型、字段标签如下:



创建数据元素ZGTIDT,描述、数据类型、字段标签如下:



显示表VBRK,转到附加结构,并点击创建附加,填写附加名称“ZZVBRK_APPEND_GTI”,结构名称应当以“ZZ”打头。



填入组件“ZZGTI_NUM”和“ZZGTI_DAT”,用先前创建的数据元素作为组件类型,确保组件名称也是以“ZZ”打头。


6.3 创建处理程序


主程序SAPMV60A中的所有包含文件都是以MV60AF打头的,所以我们创建一个独立的程序ZMV60AF_CUST_HEAD来存放所有的处理代码。



 

转到资源库浏览器,创建屏幕6001,确保屏幕类型设置为“子屏幕”。





转到屏幕6001的逻辑流,编辑PBO和PAI代码,双击PBO_6001,在主程序ZMV60AFZ_CUST_HEAD中创建输出前处理模块,编写自定义的代码,最后再回到屏幕6001点击格式,进入下一步。



在屏幕绘制器上按F6打开字典/程序字段窗口,在表/字段名称中输入VBRK,然后点击从字典获取,选择要在屏幕上显示的字段。


6.4 屏幕增强


在主程序SAPMV60A的屏幕6001中双击CUST_HEAD_ACTIVATE直到对应的FORM,然后按Shift+F4进行增强



选择菜单编辑-->增强操作->显示隐式增强选项



FORM CUST_HEAD_ACTIVATE.下一行点击右键,选择增强操作-->创建实施,选择增强模式为声明



创建新的增强实施ZGTI_SAPMV60A



这里提供两种方案来实施增强,建议使用B方案

  1. PERFORM … IN PROGRAM … IF FOUND

  2. CALL BADI … (自定义业务加载项)






方案 A: PERFORM … IN PROGRAM ... IF FOUND




在增强实施中编写自己的代码,在PERFORM … IN PROGRAM …的语法中不要忘记追加IF FOUND,涉及详细逻辑的代码可以在程序ZMV60AFZ_CUST_HEAD中编写,可以参考WB2_IVGUI_LAYOUT_H->ACTIVATE_TAB_PAGE



业务加载项BADI_SD_CUST_HEAD的另外三个方法是用在屏幕6101中,建议不管当前是否有使用到,都应当进行增强到程序ZMV60AFZ_CUST_HEAD中以预留将来可以方便的修改,所有的增强实施都应当使用同一个名称ZGTI_SAPMV60A,这样我们可以方便地使用SE20查看所有的增强。














方案 B: CALL BADI … (custom BADI)




使用自定义业务加载项是比较好的方式,以创建接口开始,可以参考IF_EX_BADI_SD_CUST_HEAD。我们转到SE24来创建ZIF_EX_BADI_SD_CUST_HEAD



参考IF_EX_BADI_SD_CUST_HEAD来设置方法和参数,并为ACTIVATE_TAB_PAGE增加FTAB的导出参数作为选项卡的说明文字,再增加一个CHECK_BADI_ACTIVATE的方法来检查标准的业务加载项是否已经激活。



接口准备好后,就可以到SE20来创建增强点ZES_GTI_SAPMV60A



增强点元素定义中,我们创建一个业务加载项定义ZBADI_SD_CUST_HEAD



将我们先前创建的接口ZIF_EX_BADI_SD_CUST_HEAD分配进来。



取消“多种用法”的选项。



创建业务加载项实施ZGTI_BADI_SD_CUST_HEAD,并在弹出的窗口填写实施类ZCL_IM_GTI_BADI_SD_CUST_HEAD



双击或通过SE19可以查看业务加载项实施ZGTI_BADI_SD_CUST_HEAD



在方法名称上双击以创建方法实施





为实施类ZCL_IM_GTI_BADI_SD_CUST_HEAD分配别名



为相关的实施方法编写自己的代码,不要忘记检查标准的业务加载项是否激活,可以参考标准业务加载项实施WB2_IVGUI_LAYOUT_H的方法代码。









最后,在主程序SAPMV60A的屏幕60016101对应的增强实施中编写自己的代码,简单使用CALL BADI即可。




6.5 验证


VF02修改发票凭证,转到抬头-->附加数据,填写相关的数据并保存,然后检查表VBRK发现附加数据已经保存成功。



用VF03查看发票凭证,自定义选项卡中的附加数据是只读的。



当我们再次启用“全球贸易管理”,我们的自定义选项卡会被替换,不会影响标准的配置控制。


7. 最佳实践


尽量不要直接在增强实施中写具体逻辑,创建自定义业务加载项是一个比较好的选择,不要忘记预留足够的参数并且需要检查调用的有效性,以避免可能的影响,并且将来如果要再调整增强的逻辑的时候,可以很容易的通过SE20来控制。

由于FORMS是一个过期的ABAP语法,在生产环境不建议使用方案A。

8. 引用