SAP 多线程删除采购申请

在项目上遇到了这么一个需求

之前顾问的一个功能平台有一个删除采购申请的功能,如果多行删除,或者多个采购申请一起删除,速度会非常慢,甚至几个采购申请就需要几分钟

看了之前的代码发现,原来之前的顾问在进行采购申请删除时,是每一行调用一次BAPI,相当于如果一个采购申请有30行,就进行了30次BAPI调用

并且还进行COMMIT,导致效率低下,所以现在改成相同的采购申请不同的行只调用一次BAPI,然后多个再进行多线程改造,效率大大提升

先看SPTA架构下多线程的流程走向

再看ALV数据

需要注意的点

*┏--------Begin-------- Add By AiQing 25.04.2025 14:43:11 -------------
*&--- 多线程
    DATA LT_LIST TYPE TABLE OF TY_PRLIST.
    LOOP AT GT_LIST ASSIGNING FIELD-SYMBOL(<FS_LIST>) WHERE CHK = 'X'.
      APPEND <FS_LIST> TO GT_LIST_DEL.
      APPEND <FS_LIST> TO LT_LIST.
    ENDLOOP.

    SORT GT_LIST_DEL BY BANFN.
    DELETE ADJACENT DUPLICATES FROM GT_LIST_DEL COMPARING BANFN.

    CALL FUNCTION 'SPTA_PARA_PROCESS_START_2'
      EXPORTING
        SERVER_GROUP             = 'parallel_generators'
        BEFORE_RFC_CALLBACK_FORM = 'BEFORE_RFC_CALLBACK_FORM'
        IN_RFC_CALLBACK_FORM     = 'IN_RFC_CALLBACK_FORM'
        AFTER_RFC_CALLBACK_FORM  = 'AFTER_RFC_CALLBACK_FORM'
        CALLBACK_PROG            = SY-REPID
      CHANGING
        USER_PARAM               = LT_LIST
      EXCEPTIONS
        INVALID_SERVER_GROUP     = 1
        NO_RESOURCES_AVAILABLE   = 2.

* -------- End -------------------------------------------------------┛

BEFORE_RFC_CALLBACK_FORM

*&---------------------------------------------------------------------*
*& Form parallel_process
*&---------------------------------------------------------------------*
FORM BEFORE_RFC_CALLBACK_FORM USING    US_BEFORE_RFC_IMP   TYPE SPTA_T_BEFORE_RFC_IMP
                              CHANGING CS_BEFORE_RFC_EXP   TYPE SPTA_T_BEFORE_RFC_EXP
                                       CT_RFCDATA          TYPE SPTA_T_INDXTAB
                                       CT_FAILED_OBJECTS   TYPE SPTA_T_FAILED_OBJECTS
                                       CT_OBJECTS_IN_TASK  TYPE SPTA_T_PENDING_OBJECTS
                                       CT_USER_PARAM       TYPE GTY_PRLIST. "这里需要定义表类型,否则会DUMP


  DATA:LT_REQUEST TYPE GTY_PRLIST.

* 按实际需求进行分批,比如同一订单号为一批数据
  LOOP AT GT_LIST_DEL INTO DATA(LS_LIST_DEL).

    LOOP AT CT_USER_PARAM INTO DATA(LS_USER_PARAM) WHERE BANFN = LS_LIST_DEL-BANFN.
      APPEND LS_USER_PARAM TO LT_REQUEST.
      DELETE TABLE CT_USER_PARAM FROM LS_USER_PARAM.
    ENDLOOP.

    DELETE GT_LIST_DEL INDEX 1.
    EXIT.
  ENDLOOP.

* 将数据转换为SPTA框架所需要的类型
  CALL FUNCTION 'SPTA_INDX_PACKAGE_ENCODE'
    EXPORTING
      DATA    = LT_REQUEST
    IMPORTING
      INDXTAB = CT_RFCDATA.

  IF LT_REQUEST IS NOT INITIAL.
    CS_BEFORE_RFC_EXP-START_RFC = 'X'.
  ELSE.
    CS_BEFORE_RFC_EXP-START_RFC = ''.
  ENDIF.

ENDFORM.

IN_RFC_CALLBACK_FORM

*&---------------------------------------------------------------------*
*& Form in_rfc_callback_form
*&---------------------------------------------------------------------*
FORM IN_RFC_CALLBACK_FORM USING    US_IN_RFC_IMP  TYPE SPTA_T_IN_RFC_IMP
                          CHANGING CS_IN_RFC_EXP  TYPE SPTA_T_IN_RFC_EXP
                                   CT_RFCDATA     TYPE SPTA_T_INDXTAB.

  DATA:LT_REQUEST TYPE GTY_PRLIST,
       LS_MESSAGE TYPE GTY_MESSAGE.

  DATA: LT_PRITEM  TYPE TABLE OF BAPIMEREQITEMIMP.
  DATA: LT_PRITEMX TYPE TABLE OF BAPIMEREQITEMX.
  DATA: LT_RETURN  LIKE TABLE OF BAPIRET2.

* 将数据转换为实际处理所需要的可读类型
  CALL FUNCTION 'SPTA_INDX_PACKAGE_DECODE'
    EXPORTING
      INDXTAB = CT_RFCDATA
    IMPORTING
      DATA    = LT_REQUEST.

* 调用BAPI
  LOOP AT LT_REQUEST ASSIGNING FIELD-SYMBOL(<LS_REQUEST>).

    APPEND VALUE #(  PREQ_ITEM  = <LS_REQUEST>-BNFPO
                     DELETE_IND = 'X' ) TO LT_PRITEM.

    APPEND VALUE #(  PREQ_ITEM  = <LS_REQUEST>-BNFPO
                     DELETE_IND = 'X' ) TO LT_PRITEMX.

    AT LAST.

      CALL FUNCTION 'BAPI_PR_CHANGE'
        EXPORTING
          NUMBER  = <LS_REQUEST>-BANFN
        TABLES
          PRITEM  = LT_PRITEM
          PRITEMX = LT_PRITEMX
          RETURN  = LT_RETURN.

      CLEAR LS_MESSAGE.
      LOOP AT LT_RETURN INTO DATA(LS_RETURN) WHERE TYPE CA 'AEX'.
        CONCATENATE LS_RETURN-MESSAGE LS_MESSAGE-MESSAGE ';' INTO LS_MESSAGE-MESSAGE.
      ENDLOOP.

      LS_MESSAGE-BANFN = <LS_REQUEST>-BANFN.
      LS_MESSAGE-BNFPO = <LS_REQUEST>-BNFPO.

      IF LS_MESSAGE-MESSAGE IS NOT INITIAL.
        LS_MESSAGE-TYPE  = 'E'.
        CALL FUNCTION 'BAPI_TRANSACTION_ROLLBACK'.
      ELSE.
        LS_MESSAGE-TYPE  = 'S'.
        LS_MESSAGE-MESSAGE  = '删除成功'.
        CALL FUNCTION 'BAPI_TRANSACTION_COMMIT'
          EXPORTING
            WAIT = 'X'.
      ENDIF.

      APPEND LS_MESSAGE TO GT_MESSAGE.

    ENDAT.

  ENDLOOP.

* 将数据转换为SPTA框架所需要的类型
  CALL FUNCTION 'SPTA_INDX_PACKAGE_ENCODE'
    EXPORTING
      DATA    = GT_MESSAGE
    IMPORTING
      INDXTAB = CT_RFCDATA.

ENDFORM.

AFTER_RFC_CALLBACK_FORM

*&---------------------------------------------------------------------*
*& Form after_rfc_callback_form
*&---------------------------------------------------------------------*
FORM AFTER_RFC_CALLBACK_FORM USING    UT_RFCDATA         TYPE SPTA_T_INDXTAB
                                      UV_RFCSUBRC        TYPE SY-SUBRC
                                      UV_RFCMSG          TYPE SPTA_T_RFCMSG
                                      UT_OBJECTS_IN_TASK TYPE SPTA_T_PENDING_OBJECTS
                                      US_AFTER_RFC_IMP   TYPE SPTA_T_AFTER_RFC_IMP
                             CHANGING CS_AFTER_RFC_EXP   TYPE SPTA_T_AFTER_RFC_EXP
                                      CT_USER_PARAM      TYPE GTY_PRLIST.


  DATA:LT_MESSAGE TYPE TABLE OF GTY_MESSAGE.

* 将数据转换为实际处理所需要的可读类型
  CALL FUNCTION 'SPTA_INDX_PACKAGE_DECODE'
    EXPORTING
      INDXTAB = UT_RFCDATA
    IMPORTING
      DATA    = LT_MESSAGE.

  READ TABLE LT_MESSAGE INTO DATA(LS_MESSAGE) INDEX 1.

  IF LS_MESSAGE-TYPE = 'S'.
    DELETE GT_LIST WHERE BANFN = LS_MESSAGE-BANFN AND CHK = 'X'.
  ELSE.
    CLEAR GS_LIST.
    GS_LIST-ICON = COND #( WHEN LS_MESSAGE-TYPE = 'E' THEN GC_RED ELSE GC_GREEN ).
    GS_LIST-MESSAGE = LS_MESSAGE-MESSAGE.
    MODIFY GT_LIST FROM GS_LIST TRANSPORTING ICON MESSAGE WHERE BANFN = LS_MESSAGE-BANFN AND CHK = 'X'.
  ENDIF.

ENDFORM.

 

posted @ 2025-04-27 17:30  艾靑  阅读(116)  评论(0)    收藏  举报