第一次接到业务部门要求在ME51N采购申请单里加字段的需求时,我其实有点懵。设备编号、外围单号这些字段在标准SAP里根本没有,但业务部门说这些数据对后续设备管理和财务核算至关重要。经过深入沟通,我们明确了几个关键点:
建议在动手前先画个简单的字段映射表,比如我当时的记录:
| 字段名 | 数据类型 | 长度 | 必填 | 用途说明 |
|---|---|---|---|---|
| ZSBH(设备编号) | CHAR | 20 | 否 | 关联固定资产卡片 |
| ZWWBH(外围单号) | CHAR | 30 | 是 | 外部系统单据关联 |
技术准备方面需要检查三件事:
实际开发中我发现,直接在CI_EBANDB里加字段比想象中复杂。首先要用SE11打开这个结构,找到最后的位置追加字段。这里有个坑要注意:SAP标准结构修改会弹出警告,需要点"是"继续。
abap复制DATA: BEGIN OF CI_EBANDB.
INCLUDE STRUCTURE EBAN.
DATA: ZSBH TYPE CHAR20, "设备编号
ZWWBH TYPE CHAR30, "外围单号
ZYT TYPE CHAR50, "用途
END OF CI_EBANDB.
改完记得激活,然后立即去SE16N查这个结构确认修改生效。我遇到过修改后没及时激活,导致后续开发报错的情况。
字段属性设置也有讲究:
用CMOD创建增强项目时,项目名最好按规范来,比如ZMM_MEREQ001。关键是要找到正确的增强点:
全局定义部分要特别注意数据类型匹配。我在ZXM02TOP里是这么定义的:
abap复制*&---------------------------------------------------------------------*
*& 包含 ZXM02TOP
*&---------------------------------------------------------------------*
DATA: gv_input TYPE flag VALUE 'X'. "控制字段可编辑性
DATA: gv_aktvt TYPE aktvt. "单据操作类型
功能出口EXIT_SAPLMEREQ_001负责初始化字段值。这里有个实用技巧:通过get_activity方法判断是创建(A)还是显示(V)操作:
abap复制CALL METHOD im_req_item->get_activity
RECEIVING
re_aktvt = gv_aktvt.
CASE gv_aktvt.
WHEN 'A'. "创建
gv_input = 'X'.
WHEN 'V'. "显示
gv_input = space.
ENDCASE.
EXIT_SAPLMEREQ_003用于保存数据,这里要注意字段映射一定要准确:
abap复制IF im_req_item IS NOT INITIAL.
i_mereq_item = im_req_item->get_data( ).
MOVE-CORRESPONDING ci_ebandb TO i_mereq_item.
CALL METHOD im_req_item->set_data( i_mereq_item ).
ex_changed = abap_true.
ENDIF.
屏幕111的开发是最考验细节的部分。首先在SE80里创建子屏幕0111,布局要符合SAP标准:
STATUS_0111模块的控制逻辑很关键,我优化后的版本是这样的:
abap复制MODULE status_0111 OUTPUT.
IF sy-tcode = 'ME53N'. "显示模式
LOOP AT SCREEN.
screen-input = '0'.
MODIFY SCREEN.
ENDLOOP.
ELSE.
LOOP AT SCREEN.
"设备编号在ME51N可编辑,ME52N仅当特定条件可编辑
IF screen-name = 'CI_EBANDB-ZSBH'.
screen-input = COND #( WHEN sy-tcode = 'ME51N' THEN '1'
ELSE gv_input ).
"外围单号始终可编辑
ELSEIF screen-name = 'CI_EBANDB-ZWWBH'.
screen-input = '1'.
ENDIF.
MODIFY SCREEN.
ENDLOOP.
ENDIF.
ENDMODULE.
校验逻辑建议放在EXIT_SAPLMEREQ_010里,比如外围单号的必输校验:
abap复制IF ci_ebandb-zwwbh IS INITIAL AND
ci_ebandb-matkl = 'ROH'. "仅原材料需要外围单号
MESSAGE e398(00) WITH '原材料必须输入外围单号'.
ENDIF.
要让自定义字段能通过BAPI传递,需要扩展两个结构:
具体实现时我封装了个专门处理增强字段的方法:
abap复制METHOD fill_extensionin.
DATA: ls_extensionin TYPE bapiparex,
ls_te_item TYPE bapi_te_mereqitem,
ls_te_itemx TYPE bapi_te_mereqitemx.
ls_te_item-preq_item = iv_item_no.
ls_te_item-zsbh = iv_equip_no. "设备编号
ls_te_item-zwwbh = iv_ext_doc. "外围单号
ls_te_itemx-preq_item = iv_item_no.
ls_te_itemx-zsbh = abap_true. "标识更新设备编号
ls_te_itemx-zwwbh = abap_true. "标识更新外围单号
ls_extensionin-structure = 'BAPI_TE_MEREQITEM'.
ls_extensionin-valuepart1 = ls_te_item.
APPEND ls_extensionin TO ct_extensionin.
ls_extensionin-structure = 'BAPI_TE_MEREQITEMX'.
ls_extensionin-valuepart1 = ls_te_itemx.
APPEND ls_extensionin TO ct_extensionin.
ENDMETHOD.
调用BAPI时这样传参:
abap复制CALL FUNCTION 'BAPI_PR_CREATE'
EXPORTING
prheader = ls_header
prheaderx = ls_headerx
IMPORTING
number = lv_pr_number
TABLES
return = lt_return
pritem = lt_items
pritemx = lt_itemsx
extensionin = lt_extensionin. "这里传增强字段
开发完成后我建议分三个阶段测试:
单元测试:单独测试每个增强点
集成测试:通过BAPI创建采购申请
abap复制DATA(lt_extensionin) = VALUE bapiparex_tab(
( structure = 'BAPI_TE_MEREQITEM'
valuepart1 = VALUE #(
preq_item = '00010'
zsbh = 'EQ-20230001'
zwwbh = 'PO-EXT-001' ) )
( structure = 'BAPI_TE_MEREQITEMX'
valuepart1 = VALUE #(
preq_item = '00010'
zsbh = abap_true
zwwbh = abap_true ) )
).
用户验收测试:让业务部门实际操作验证
常见问题排查技巧:
做完增强一定要写好技术文档,我通常包含这些内容:
增强点清单:
字段对应表:
| 屏幕字段 | 数据库字段 | BAPI字段 |
|---|---|---|
| 设备编号 | EBAN-ZSBH | BAPI_TE_MEREQITEM-ZSBH |
注意事项:
维护阶段发现,当业务部门需要新增字段时,按照这个模式可以快速扩展。最近我们又增加了"项目阶段"字段,只用了2小时就完成全部开发。