一、采购订单屏幕增强,主要涉及增强点SMOD MM06E005或者BADI ME_GUI_PO_CUST,
本次示例使用增强SMOD MM06E005,BADI ME_GUI_PO_CUST可参考SAP标准示例(SE18->转到->示例代码->显示)。
1、抬头屏幕增强
① 在结构CI_EKKODB和CI_EKKODBX中添加字段
②在函数组XM06生成屏幕0101,并绘制屏幕,其中输入输出框建议给组1赋值,以便控制屏幕是否可输入,如下图所示
③ 修改屏幕逻辑流,控制是否可输入必须添加,其余搜索帮助或者增加描述字段可根据需求添加
设置字段可否编辑、显示与隐藏PBO事件代码可添加在INCLUDE ZXM06ZZZ中,代码如下:
MODULE status_0101 OUTPUT.
* SET PF-STATUS 'xxxxxxxx'.
* SET TITLEBAR 'xxx'.
CASE gv_trtyp_c.
WHEN 'A'.
LOOP AT SCREEN.
IF gv_trtyp_c = 'A'.
screen-input = 0.
MODIFY SCREEN.
ENDIF.
ENDLOOP.
WHEN 'V'.
IF sy-tcode = 'ME29N'.
CLEAR: lv_kzfae.
SELECT SINGLE kzfae INTO @lv_kzfae
FROM t16fb
WHERE frgke = @ekko-frgke.
IF sy-subrc = 0 AND lv_kzfae = 1.
LOOP AT SCREEN.
screen-input = 0.
MODIFY SCREEN.
ENDLOOP.
ENDIF.
ENDIF.
WHEN OTHERS.
ENDCASE.
LOOP AT SCREEN.
IF screen-group1 = 'G1'.
AUTHORITY-CHECK OBJECT 'YMM_GJ_EKO'
ID 'EKORG' FIELD ekko-ekorg
ID 'ACTVT' FIELD '01'.
IF sy-subrc <> 0.
screen-active = 0.
MODIFY SCREEN.
ASSIGN (screen-name) TO FIELD-SYMBOL(<fs_any>).
IF sy-subrc = 0.
CLEAR <fs_any>.
ENDIF.
ENDIF.
ENDIF.
ENDLOOP.
ENDMODULE.
④将值传递到屏幕使用函数出口EXIT_SAPMM06E_006,控制屏幕字段可否编辑变量gv_trtyp_c(事务类型)定义在INCLUDE ZXM06TOP中,赋值也在此函数中:
⑤将屏幕值传回使用函数出口EXIT_SAPMM06E_008:
2、行项目屏幕增强
① 在结构CI_EKPODB和CI_EKPODBX中添加字段
②行项目同抬头类似,在函数组XM06生成屏幕0111,并绘制屏幕,如下图所示
③ 修改屏幕逻辑流,控制是否可输入必须添加,其余搜索帮助或者增加描述字段可根据需求添加
MODULE status_0111 OUTPUT.
* SET PF-STATUS 'xxxxxxxx'.
* SET TITLEBAR 'xxx'.
CASE gv_aktyp_c.
WHEN 'A'.
LOOP AT SCREEN.
screen-input = 0.
MODIFY SCREEN.
ENDLOOP.
WHEN 'V'.
IF sy-tcode = 'ME29N'.
SELECT SINGLE kzfae INTO @DATA(lv_kzfae)
FROM t16fb
WHERE frgke = @ekko-frgke.
IF sy-subrc = 0 AND lv_kzfae = 1.
LOOP AT SCREEN.
screen-input = 0.
MODIFY SCREEN.
ENDLOOP.
ENDIF.
ENDIF.
WHEN OTHERS.
ENDCASE.
IF sy-tcode = 'ME21N' OR sy-tcode = 'ME22N' OR sy-tcode = 'ME29N'
OR ( sy-tcode = 'ME23N' AND gv_aktyp_c = 'V' ).
AUTHORITY-CHECK OBJECT 'Z_SYC_PUR'
ID 'ACTVT' FIELD '02'.
IF sy-subrc <> 0.
IF NOT ekpo_ci-zzsyst IS INITIAL.
"MESSAGE e000(zmm) WITH '您没有修改外围系统同步订单的权限'.
LOOP AT SCREEN.
screen-input = 0.
MODIFY SCREEN.
ENDLOOP.
ELSE.
LOOP AT SCREEN.
IF screen-group1 = 'G1'.
screen-input = 0.
MODIFY SCREEN.
ENDIF.
ENDLOOP.
ENDIF.
ENDIF.
ENDIF.
ENDMODULE.
④将值传递到屏幕使用函数出口EXIT_SAPMM06E_016:
⑤将屏幕值传回使用函数出口EXIT_SAPMM06E_018:
二、采购订单逻辑增强,主要是对增强点 ME_PROCESS_PO_CUST进行增强实施,
check方法如下代码所示:
METHOD if_ex_me_process_po_cust~check.
INCLUDE mm_messages_mac.
DATA: l_head TYPE mepoheader,
l_item TYPE mepoitem,
items TYPE purchase_order_items,
item_obj TYPE purchase_order_item,
account TYPE purchase_order_accountings,
account_obj TYPE purchase_order_accounting,
ls_account TYPE mepoaccounting, "科目分配字段结构.
lv_type TYPE char1.
** sy-tcode = 'ME21N' OR sy-tcode = 'ME22N' OR sy-tcode = 'ME29N' .
CHECK NOT im_header IS INITIAL.
l_head = im_header->get_data( ). "获取抬头
items = im_header->get_items( ) . "获取行项目
****根据抬头输入的公司代码BUKRS,取表YTGYLCONF02取值
****国际:如果取到的ZBUS_LINE='3’,则检查利润中心,并且
**** 如果采购渠道或船(次)号为空,则报错“请检查采购渠道、船(次)号必须输入”,
**** 如果合同号或净额结算为空,则警告“请检查合同号、净额结算是否需要输入”
****船舶:如果取到的ZBUS_LINE='4’,则警告“请检查船(次)号、合同号是否需要输入”
SELECT SINGLE ybus_line
INTO @DATA(lv_busline)
FROM ytgylconf02
WHERE bukrs = @l_head-bukrs.
IF sy-subrc = 0.
IF lv_busline = '3'.
IF l_head-zzcgqd IS INITIAL OR l_head-zzaufnr IS INITIAL.
mmpur_business_obj_id l_head-id.
mmpur_context mmcnt_context_badi.
mmpur_message_forced 'E' 'ZMM' '010' space space space space.
ch_failed = 'X'.
ENDIF.
IF l_head-zzhth IS INITIAL OR l_head-zzjejs IS INITIAL.
MESSAGE w013(zmm).
mmpur_business_obj_id l_head-id.
mmpur_context mmcnt_context_badi.
mmpur_message_forced 'W' 'ZMM' '013' space space space space.
ENDIF.
LOOP AT items INTO item_obj.
l_item = item_obj-item->get_data( ).
IF l_item-knttp = 'I'.
account = item_obj-item->get_accountings( ).
LOOP AT account INTO account_obj.
ls_account = account_obj-accounting->get_data( ).
IF ls_account-prctr IS INITIAL OR ls_account-prctr = '9999999999'.
mmpur_business_obj_id l_item-id.
mmpur_context mmcnt_context_badi.
mmpur_message_forced 'E' 'ZMM' '012' '行项目' l_item-ebelp space space.
CALL METHOD item_obj-item->invalidate( ).
ch_failed = 'X'.
ENDIF.
CLEAR: ls_account.
ENDLOOP.
ENDIF.
CLEAR: item_obj,
l_item,
account.
ENDLOOP.
ELSEIF lv_busline = '4'.
IF l_head-zzaufnr IS INITIAL OR l_head-zzhth IS INITIAL.
MESSAGE w011(zmm).
mmpur_business_obj_id l_head-id.
mmpur_context mmcnt_context_badi.
mmpur_message_forced 'W' 'ZMM' '011' space space space space.
ENDIF.
ENDIF.
ENDIF.
****校验船(次)号的内部订单类型是否为XA18
IF l_head-zzaufnr IS NOT INITIAL.
SELECT SINGLE auart
INTO @DATA(lv_auart)
FROM aufk
WHERE aufnr = @l_head-zzaufnr.
IF sy-subrc <> 0 OR lv_auart <> 'XA18'.
mmpur_business_obj_id l_head-id.
mmpur_context mmcnt_context_badi.
mmpur_message_forced 'E' 'ZMM' '009' space space space space.
ch_failed = 'X'.
ENDIF.
ENDIF.
ENDMETHOD.
其中有几点注意点:
1. 使用宏 mmpur_message_forced 将消息添加至消息弹框中。
2. 添加消息之前需指定是抬头消息还是行项目消息,使用宏 mmpur_business_obj_id 指定。
3. 增强的消息使用宏 mmpur_context 设置context值为常量 mmcnt_context_badi(12),因为维护SAP标准字段与增强字段所走的代码逻辑不一致,清空消息则是根据context值,所以如果不特殊赋值则可能context值当前为 mmcnt_context_default(5),如果仅仅修改增强字段则不会清空context值为 mmcnt_context_default(5)的消息,那即使校验通过原先的消息依然存在。
4. 此方法如果使用了Message语句抛出消息,但并不会在前台看到。。。
所以所以,用户提了个需求,说他们操作习惯不点检查,这样很容易忽略警告消息,希望在任一屏幕回车时候能看到消息。如果仅仅是增强屏幕回车则可以直接在增强屏幕添加PAI事件,但需求是标准屏幕回车也要触发,这又由于仅修改增强子屏幕的字段值与标准屏幕的处理逻辑不一样,而且没有回车没有用户出口或者BADI增强点,最终在我费了九牛二虎之力后确定了一个都会走的隐式增强点:类 CL_SCREEN_VIEW_MM 方法 PAI_FINISHED,代码如下:
METHOD PAI_FINISHED.
* ...
"""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""$"$\SE:(1) Class CL_SCREEN_VIEW_MM, Method PAI_FINISHED, End A
*$*$-Start: (1)---------------------------------------------------------------------------------$*$*
ENHANCEMENT 1 YENH_MEPO_CHECK. "active version
DATA: ls_ekko TYPE ekko,
lv_busline TYPE ytgylconf02-ybus_line.
IF ( sy-tcode = 'ME21N' OR sy-tcode = 'ME22N' ) AND sy-ucomm = ''.
ASSIGN ('(SAPLMEPO)EKKO') TO FIELD-SYMBOL(<fs_ekko>).
IF sy-subrc = 0 AND <fs_ekko> IS ASSIGNED.
MOVE-CORRESPONDING <fs_ekko> TO ls_ekko.
* 根据抬头输入的公司代码BUKRS,取表YTGYLCONF02取值
* 国际:如果取到的ZBUS_LINE='3’,则检查利润中心,并且
* 如果采购渠道或船(次)号为空,则报错“请检查采购渠道、船(次)号必须输入”,
* 如果合同号或净额结算为空,则警告“请检查合同号、净额结算是否需要输入”
* 船舶:如果取到的ZBUS_LINE='4’,则警告“请检查船(次)号、合同号是否需要输入”
SELECT SINGLE ybus_line
INTO lv_busline
FROM ytgylconf02
WHERE bukrs = ls_ekko-bukrs.
IF sy-subrc = 0.
IF lv_busline = '3'.
IF ls_ekko-zzhth IS INITIAL OR ls_ekko-zzjejs IS INITIAL.
MESSAGE s013(zmm) DISPLAY LIKE 'W'.
ENDIF.
IF ls_ekko-zzcgqd IS INITIAL OR ls_ekko-zzaufnr IS INITIAL.
MESSAGE s010(zmm) DISPLAY LIKE 'E'.
ENDIF.
ELSEIF lv_busline = '4'.
IF ls_ekko-zzaufnr IS INITIAL OR ls_ekko-zzhth IS INITIAL.
MESSAGE s011(zmm) DISPLAY LIKE 'W'.
ENDIF.
ENDIF.
ENDIF.
ENDIF.
ENDIF.
ENDENHANCEMENT.
*$*$-End: (1)---------------------------------------------------------------------------------$*$*
ENDMETHOD.
这里需注意由于不能让屏幕灰色显示,所以这消息需要定义成S类型,使用DISPLAY LIKE其他消息类型显示。