ABAP添加VF02输出类型并重新触发IDOC出站

需求背景:

有些新产品是先卖给客户,客户用一段时间后才谈价钱,所以系统首次开票的价格不一定是最终价格,当发现当前价格跟开票时的价格不一样时,需要将最新的价格重新推送给客户,系统采用的是标准IDOC的方式实现。

实现过程:

步骤1.拉取已发送过IDOC的发票数据,并检查是否和当前价格一致。

步骤2.新添加一条输出类型至OUTPUT。

步骤3.重新触发IDOC的出站。

步骤4:出站时将IDOC对应节点下的值改为当前最新的价格。


步骤1代码:

获取发票代码:

* Get Billing document
  SELECT a~vbeln,
         a~fkdat,
         c~kdmat,
         d~kunnr,
         a~vkorg,
         a~vtweg,
         b~vkbur,
         a~knumv,
         a~bukrs,
         a~belnr,
         a~gjahr,
         b~posnr,
         b~matnr,
         e~maktx,
         f~bismt,
         b~fkimg,
         b~vrkme,
         b~werks,
         b~aubel,
         b~aupos,
         CAST( a~vbeln AS CHAR( 30 ) ) AS objky
    INTO TABLE @lt_invoices
    FROM vbrk AS a
   INNER JOIN vbrp AS b
      ON a~vbeln = b~vbeln
   INNER JOIN vbap AS c
      ON b~aubel = c~vbeln
     AND b~aupos = c~posnr
   INNER JOIN vbpa AS d
      ON a~vbeln = d~vbeln
     AND d~posnr = 000000
     AND d~parvw = 'RE'
    LEFT OUTER JOIN makt AS e
      ON b~matnr = e~matnr
     AND e~spras = @sy-langu
    LEFT OUTER JOIN mara AS f
      ON b~matnr = f~matnr
   WHERE a~vbeln IN @s_vbeln
     AND a~fkdat IN @s_fkdat
     AND d~kunnr IN @s_kunre
     AND a~vkorg IN @s_vkorg
     AND a~vtweg IN @s_vtweg
     AND b~vkbur IN @s_vkbur
     AND c~kdmat IN @s_kdmat.

获取历史IDOC发送状态等信息:

    DATA(lt_copy) = lt_invoices.
    DELETE ADJACENT DUPLICATES FROM lt_copy COMPARING vbeln.

*   Get IDOC output info
    SELECT a~kappl,
           a~objky,
           a~kschl,
           a~spras,
           a~parnr,
           a~parvw,
           a~erdat,
           a~eruhr,
           a~nacha,
           a~vstat,
           a~tdcovtitle,
           a~cmfpnr,
           a~datvr,
           a~uhrvr,
           b~aplid,
           b~nr,
           b~msgcnt,
           b~arbgb,
           b~msgnr,
           b~msgv1,
           c~status
      INTO TABLE @DATA(lt_nast)
      FROM nast AS a
     INNER JOIN cmfp AS b
        ON a~cmfpnr = b~nr
       AND b~aplid = 'WFMC'
       AND b~arbgb = 'E0' AND b~msgnr = '045'
      LEFT OUTER JOIN edidc AS c
        ON b~msgv1 = c~docnum
       FOR ALL ENTRIES IN @lt_copy
     WHERE a~kappl = 'V3'
       AND a~objky = @lt_copy-objky
       AND a~kschl = 'RD00'
       AND a~spras = @sy-langu
       AND a~parnr = @lt_copy-kunnr
       AND a~parvw = 'RE'.

    DELETE ADJACENT DUPLICATES FROM lt_invoices
      COMPARING vbeln posnr aubel aupos.

    SORT lt_nast BY objky ASCENDING
                    erdat DESCENDING
                    eruhr DESCENDING.

获取发票开票时金额:

*   Get Billing price
    SELECT knumv,
           kposn,
           stunr,
           zaehk,
           kappl,
           kschl,
           kbetr,
           waers,
           kpein,
           kmein
      INTO TABLE @DATA(lt_prcd_elements)
      FROM prcd_elements
       FOR ALL ENTRIES IN @lt_invoices
     WHERE knumv = @lt_invoices-knumv
       AND kposn = @lt_invoices-posnr
       AND kappl = 'V'
       AND kschl = 'PR00'.

    SORT lt_prcd_elements BY knumv ASCENDING
                             kposn ASCENDING.

获取当前销售价格:

*   Get sales condition price
    SELECT a~kappl,
           a~kschl,
           a~vkorg,
           a~vtweg,
           a~vkbur,
           a~kunnr,
           a~matnr,
           a~kfrst,
           a~datbi,
           a~datab,
           a~knumh,
           b~kopos,
           b~kbetr,
           b~konwa,
           b~kpein,
           b~kmein
      INTO TABLE @lt_konp
      FROM a996 AS a
     INNER JOIN konp AS b
        ON a~knumh = b~knumh
       FOR ALL ENTRIES IN @lt_invoices
     WHERE a~kappl =  'V'
       AND a~kschl =  'PR00'
       AND a~vkorg =  @lt_invoices-vkorg
       AND a~vtweg =  @lt_invoices-vtweg
       AND a~vkbur =  @lt_invoices-vkbur
       AND a~kunnr =  @lt_invoices-kunnr
       AND a~matnr =  @lt_invoices-matnr
       AND a~datab <= @lt_invoices-fkdat
       AND a~datbi >= @lt_invoices-fkdat.

根据IDOC号码解析历史发送内容:

*&---------------------------------------------------------------------*
*& Form frm_price_from_idoc
*&---------------------------------------------------------------------*
*& Get price from IDOC
*&---------------------------------------------------------------------*
*&      --> LS_NAST_MSGV1
*&      <-- LT_ITEM_PRICE
*&---------------------------------------------------------------------*
FORM frm_price_from_idoc  USING    uv_idoc_no TYPE cmfp-msgv1
                          CHANGING ct_item_price TYPE tt_item_price.
  DATA:
    ls_item_price TYPE ty_item_price,
    ls_e1edp01    TYPE e1edp01,
    ls_e1edp26    TYPE e1edp26.

  DATA:
    lv_idoc_number     TYPE edidc-docnum,
    ls_idoc_control    TYPE edidc,
    lt_idoc_containers TYPE STANDARD TABLE OF edidd.

  CHECK uv_idoc_no IS NOT INITIAL.

  lv_idoc_number = uv_idoc_no.

  CALL FUNCTION 'EDI_DOCUMENT_OPEN_FOR_PROCESS'
    EXPORTING
*     DB_READ_OPTION           = DB_READ
      document_number          = lv_idoc_number
*     ENQUEUE_OPTION           = SYNCHRONOUS
    IMPORTING
      idoc_control             = ls_idoc_control
    EXCEPTIONS
      document_foreign_lock    = 1
      document_not_exist       = 2
      document_number_invalid  = 3
      document_is_already_open = 4
      OTHERS                   = 5.

  IF sy-subrc <> 0.
*   Implement suitable error handling here
  ENDIF.

  CALL FUNCTION 'EDI_SEGMENTS_GET_ALL'
    EXPORTING
      document_number         = lv_idoc_number
    TABLES
      idoc_containers         = lt_idoc_containers
    EXCEPTIONS
      document_number_invalid = 1
      end_of_document         = 2
      OTHERS                  = 3.
  IF sy-subrc <> 0.
*   Implement suitable error handling here
  ENDIF.

  LOOP AT lt_idoc_containers INTO DATA(ls_idoc_containers).
    CASE ls_idoc_containers-segnam.
      WHEN 'E1EDP01'.
        IF ls_item_price IS NOT INITIAL.
          INSERT ls_item_price INTO TABLE ct_item_price.
          CLEAR ls_item_price.
        ENDIF.

        MOVE ls_idoc_containers-sdata TO ls_e1edp01.

        ls_item_price-posex = ls_e1edp01-posex.

      WHEN 'E1EDP26'.
        MOVE ls_idoc_containers-sdata TO ls_e1edp26.
        IF ls_e1edp26-qualf = '001'.
          ls_item_price-betrg = ls_e1edp26-betrg.
        ENDIF.
      WHEN OTHERS.
    ENDCASE.
  ENDLOOP.

  INSERT ls_item_price INTO TABLE ct_item_price.
  CLEAR ls_item_price.

  CALL FUNCTION 'EDI_DOCUMENT_CLOSE_PROCESS'
    EXPORTING
      document_number     = lv_idoc_number
*     BACKGROUND          = NO_BACKGROUND
*     NO_DEQUEUE          = ' '
*     STATUS_CHECK        = ' '
*     QRFC_STATE          = 'U'
*     P_EDIQI             =
*   IMPORTING
*     IDOC_CONTROL        =
    EXCEPTIONS
      document_not_open   = 1
      failure_in_db_write = 2
      parameter_error     = 3
      status_set_missing  = 4
      OTHERS              = 5.

  IF sy-subrc <> 0.
*   Implement suitable error handling here
  ENDIF.
ENDFORM.

步骤2实现:

以下函数可以为任何单据添加新的Output,本例是添加一条RD00的Output。

    ls_nast-kappl      = 'V3'.                                          "Application
    ls_nast-objky      = <fs_sel_alv>-vbeln.                            "Billing
    ls_nast-mandt      = sy-mandt.                                      "Client
    ls_nast-kschl      = 'RD00'.                                        "Message type
    ls_nast-spras      = sy-langu.                                      "Language
    ls_nast-parnr      = <fs_sel_alv>-kunre.                            "message partner
    ls_nast-parvw      = 'RE'.                                          "Partner Role
    ls_nast-objtype    = 'VBRK'.                                        "Object type
    ls_nast-tdcovtitle = 'ZPRMANUAL'.                                   "Manually flag
    ls_nast-nacha      = '6'.                                           "EDI
    ls_nast-vsztp      = '3'.                                           "Send immediately. Check domain values
    ls_nast-manue      = 'X'.                                           "Very important: message processed manually
    APPEND ls_nast TO lt_nast.

**********************************************************************
*   Step-1. test add output RD00 to VF02
**********************************************************************
    CALL FUNCTION 'RV_MESSAGES_INSERT'
*     EXPORTING
*       LV_ARCH         = ' '
      TABLES
        tab_xnast = lt_nast.

    CALL FUNCTION 'RV_MESSAGES_UPDATE'
      EXPORTING
        msg_kappl          = 'V3'
        msg_objky          = ls_nast-objky
        msg_no_update_task = 'X'.

    IF sy-subrc = 0.
      COMMIT WORK AND WAIT.

      ASSIGN ('(SAPLV61B)XNAST') TO FIELD-SYMBOL(<ls_xnast>).
    ELSE.
      ROLLBACK WORK.
      <fs_sel_alv>-icon = icon_led_red.
      <fs_sel_alv>-msg  = 'Add output failed!'.

      CLEAR:lt_nast.
      CONTINUE.
    ENDIF.
步骤3实现:

标准前台保存后触发的逻辑不好剥离出来,但是事务代码VF31可以批量处理发票的Output,是有单独的程序来处理,所以最终决定依据VF31的代码逻辑来完成重触发的实现。

VF31界面:

在查看源码后发现,选择屏幕上的信息是会将改发票下所有的output条目全部筛选出来,这不太符合我们的需求,我们应该只处理我们手工添加的那条output,所以我们将改程序copy一份出来,并添加上两个选择条件(NAST的两个主键),即可在后续调用时仅处理我们手工添加的output。

Copy标准代码SD70AV3A,并添加两个选择条件,同时利用内存传值,将处理结果抛出到内存中,用于后续输出结果。

完成上述内容后,调用copy出来的新程序来完成IDoc的重新发送:

**********************************************************************
*   Step-2. run VF31 and send immediately
**********************************************************************
    ASSIGN COMPONENT 'ERDAT' OF STRUCTURE <ls_xnast> TO FIELD-SYMBOL(<lv_erdat>).
    ASSIGN COMPONENT 'ERUHR' OF STRUCTURE <ls_xnast> TO FIELD-SYMBOL(<lv_eruhr>).

    rt_objky = VALUE #( ( sign = 'I' option = 'EQ' low = ls_nast-objky ) ).
    rt_kschl = VALUE #( ( sign = 'I' option = 'EQ' low = ls_nast-kschl ) ).
    rt_erdat = VALUE #( ( sign = 'I' option = 'EQ' low = <lv_erdat> ) ).
    rt_eruhr = VALUE #( ( sign = 'I' option = 'EQ' low = <lv_eruhr> ) ).

    SUBMIT zprsd70av3a
      WITH rg_kschl IN rt_kschl
      WITH rg_vbeln IN rt_objky
      WITH pm_verdi = abap_true
      WITH rg_erdat IN rt_erdat
      WITH rg_eruhr IN rt_eruhr
       AND RETURN.

**********************************************************************
*   Step-3. Get process result from VF31
**********************************************************************
    IMPORT msgs = msgs FROM MEMORY ID 'ZPRMEMORY_VF31'.
    FREE MEMORY ID 'ZPRMEMORY_VF31'.

    READ TABLE msgs INTO DATA(ls_msgs) INDEX 1.

*   Get process log
    SELECT aplid,
           nr,
           msgcnt,
           arbgb,
           msgnr,
           msgv1
      INTO TABLE @DATA(lt_cmfp)
      FROM cmfp
     WHERE aplid = 'WFMC'
       AND nr    = @ls_msgs-cmfpnr.

    SORT lt_cmfp BY msgnr ASCENDING.

    READ TABLE lt_cmfp INTO DATA(ls_cmfp)
      WITH KEY msgnr = '082' BINARY SEARCH.
    IF sy-subrc <> 0.
      READ TABLE lt_cmfp INTO ls_cmfp
        WITH KEY msgnr = '045' BINARY SEARCH.
    ENDIF.

    IF ls_cmfp IS INITIAL.
      <fs_sel_alv>-icon = icon_led_red.
      <fs_sel_alv>-msg  = 'IDoc send failed!'.
    ELSE.
      <fs_sel_alv>-icon = icon_led_green.

      MESSAGE ID ls_cmfp-arbgb
            TYPE gc_msgty_s
          NUMBER ls_cmfp-msgnr
            WITH ls_cmfp-msgv1
                 space
                 space
                 space
            INTO <fs_sel_alv>-msg.
    ENDIF.
步骤4实现:

IDOC的处理过程在NACE对应配置中可以看到,由指定的标准程序来完成,所以更改IDOC送信内容的逻辑需要在该子例程中debug来查找exit来完成。

CMOD:为LVEDF001创建实施:

代码实现:

**********************************************************************
* Enhancement for PSAM 20240306                                 BEGIN*
* Author: Hand15                                                  ↓ *
* Usage: Change price(E1EDP26 001) from A996 when resend IDOC manually
**********************************************************************
FIELD-SYMBOLS:<fs_tvbdpr> TYPE vbdpr.
IF sy-cprog = 'ZPRSD70AV3A'.
  DATA(lines) = lines( int_edidd[] ).
  READ TABLE int_edidd[] ASSIGNING FIELD-SYMBOL(<fs_edidd>) INDEX lines.
  IF sy-subrc = 0.
    MOVE <fs_edidd>-sdata TO ls_e1edp26.
    IF <fs_edidd>-segnam = 'E1EDP26' AND ls_e1edp26-qualf = '001'.
      ASSIGN ('(SAPLVEDF)TVBDPR') TO <fs_tvbdpr>.

*     Get current price
      SELECT SINGLE
             a~kappl,
             a~kschl,
             a~vkorg,
             a~vtweg,
             a~vkbur,
             a~kunnr,
             a~matnr,
             a~kfrst,
             a~datbi,
             a~datab,
             a~knumh,
             b~kopos,
             b~kbetr,
             b~konwa,
             b~kpein,
             b~kmein
        INTO @DATA(ls_konp)
        FROM a996 AS a
       INNER JOIN konp AS b
          ON a~knumh = b~knumh
       WHERE a~kappl =  'V'
         AND a~kschl =  'PR00'
         AND a~vkorg =  @xvbdkr-vkorg
         AND a~vtweg =  @xvbdkr-vtweg
         AND a~vkbur =  @<fs_tvbdpr>-vkbur
         AND a~kunnr =  @xvbdkr-kunre
         AND a~matnr =  @<fs_tvbdpr>-matnr
         AND a~datab <= @xvbdkr-fkdat
         AND a~datbi >= @xvbdkr-fkdat.

      IF sy-subrc = 0.
        ls_e1edp26-betrg = ls_konp-kbetr.
        CONDENSE ls_e1edp26-betrg NO-GAPS.

        MOVE ls_e1edp26 TO <fs_edidd>-sdata.
      ENDIF.
    ENDIF.
  ENDIF.
ENDIF.
**********************************************************************
* Enhancement for PSAM 20240306                                   ↑ *
* Author: Hand15                                                  END*
* Usage: Change price(E1EDP26 001) from A996 when resend IDOC manually
**********************************************************************
完整代码:
*----------------------------------------------------------------------*
* ZPRSDRRESENDBILLINGPRICE  <Resend Billing Price With IDOC>
*----------------------------------------------------------------------*
* Creation date       : 06.03.2024 17:22:34
* Authors             : HAND15
* Functional overview : Resend Billing Price With IDOC
* T-code              : ZPSD114
*----------------------------------------------------------------------*
* Revicion History
* ChangeDate  Changed by | Change TR | Changes
*
*----------------------------------------------------------------------*
REPORT zprsdrresendbillingprice.
TABLES:vbrp,vbrk,vbap,tline.
TYPES:
  BEGIN OF ty_invoices,
    vbeln TYPE vbrk-vbeln,
    fkdat TYPE vbrk-fkdat,
    kdmat TYPE vbap-kdmat,
    kunnr TYPE vbpa-kunnr,
    vkorg TYPE vbrk-vkorg,
    vtweg TYPE vbrk-vtweg,
    vkbur TYPE vbrp-vkbur,
    knumv TYPE vbrk-knumv,
    bukrs TYPE vbrk-bukrs,
    belnr TYPE vbrk-belnr,
    gjahr TYPE vbrk-gjahr,
    posnr TYPE vbrp-posnr,
    matnr TYPE vbrp-matnr,
    maktx TYPE makt-maktx,
    bismt TYPE mara-bismt,
    fkimg TYPE vbrp-fkimg,
    vrkme TYPE vbrp-vrkme,
    werks TYPE vbrp-werks,
    aubel TYPE vbrp-aubel,
    aupos TYPE vbrp-aupos,
    objky TYPE nast-objky,
  END OF ty_invoices,
  tt_invoices TYPE SORTED TABLE OF ty_invoices
    WITH NON-UNIQUE KEY vbeln posnr aubel aupos,

  BEGIN OF ty_item_price,
    posex TYPE e1edp01-posex,
    betrg TYPE e1edp26-betrg,
  END OF ty_item_price,
  tt_item_price TYPE SORTED TABLE OF ty_item_price
    WITH UNIQUE KEY posex,

  BEGIN OF ty_konp,
    kappl TYPE a996-kappl,
    kschl TYPE a996-kschl,
    vkorg TYPE a996-vkorg,
    vtweg TYPE a996-vtweg,
    vkbur TYPE a996-vkbur,
    kunnr TYPE a996-kunnr,
    matnr TYPE a996-matnr,
    kfrst TYPE a996-kfrst,
    datbi TYPE a996-datbi,
    datab TYPE a996-datab,
    knumh TYPE a996-knumh,
    kopos TYPE konp-kopos,
    kbetr TYPE konp-kbetr,
    konwa TYPE konp-konwa,
    kpein TYPE konp-kpein,
    kmein TYPE konp-kmein,
  END OF ty_konp,
  tt_konp TYPE SORTED TABLE OF ty_konp
    WITH UNIQUE KEY kappl kschl vkorg vtweg vkbur kunnr matnr kfrst datbi datab,

  ty_alv  TYPE zprsdsresendbillingprice,
  tt_alv  TYPE STANDARD TABLE OF ty_alv.

DATA:
  gt_alv     TYPE tt_alv,
  gt_sel_alv TYPE tt_alv.

DATA:
  go_alv_grid      TYPE REF TO cl_gui_alv_grid,
  gt_fieldcat      TYPE lvc_t_fcat,
  gs_layout        TYPE lvc_s_layo,
  gt_event         TYPE slis_t_event,
  gs_event         TYPE slis_alv_event,
  gs_grid_settings TYPE lvc_s_glay.

CONSTANTS:
  gc_msgty_s      TYPE msgty          VALUE 'S',
  gc_msgty_e      TYPE msgty          VALUE 'E',
  gc_bt_resend    TYPE ui_func        VALUE 'BT_RESEND',
  gc_bt_selall    TYPE ui_func        VALUE 'BT_SELALL',
  gc_bt_desel     TYPE ui_func        VALUE 'BT_DESEL',
  gc_double_click TYPE ui_func        VALUE '&IC1',
  gc_field_check  TYPE lvc_fname      VALUE 'CHECKBOX',
  gc_field_docnum TYPE lvc_fname      VALUE 'DOCNUM',
  gc_field_vbeln  TYPE lvc_fname      VALUE 'VBELN',
  gc_field_icon   TYPE lvc_fname      VALUE 'ICON',
  gc_field_msg    TYPE lvc_fname      VALUE 'MSG',
  gc_field_zindex TYPE lvc_fname      VALUE 'ZINDEX',
  gc_field_style  TYPE lvc_fname      VALUE 'STYLE',
  gc_alv_sel_mode TYPE lvc_libox      VALUE 'D',
  gc_key_ddic_alv TYPE dd02l-tabname  VALUE 'ZPRSDSRESENDBILLINGPRICE'.
*----------------------------------------------------------------------*
* Class Defination
*----------------------------------------------------------------------*
CLASS lcl_this DEFINITION CREATE PUBLIC.
  PUBLIC SECTION.
    CLASS-METHODS main.
ENDCLASS.
*----------------------------------------------------------------------*
*  Screen
*----------------------------------------------------------------------*
SELECTION-SCREEN BEGIN OF BLOCK b1 WITH FRAME TITLE TEXT-001.
  SELECT-OPTIONS:
    s_vbeln FOR vbrp-vbeln,
    s_fkdat FOR vbrk-fkdat,
    s_kunre FOR vbrp-kunre_ana,
    s_vkorg FOR vbrk-vkorg DEFAULT '2D05',
    s_vtweg FOR vbrk-vtweg DEFAULT '10',
    s_vkbur FOR vbrp-vkbur DEFAULT 'PA05',
    s_kdmat FOR vbap-kdmat,
    s_manif FOR tline-tdline NO INTERVALS.
  PARAMETERS:
    p_log AS CHECKBOX.
SELECTION-SCREEN END OF BLOCK b1.
*&---------------------------------------------------------------------*
*& INITIALIZATION
*&---------------------------------------------------------------------*
INITIALIZATION.
  PERFORM frm_initial_screen.
*&---------------------------------------------------------------------*
*& Start process
*&---------------------------------------------------------------------*
START-OF-SELECTION.
  lcl_this=>main( ).

*&---------------------------------------------------------------------*
*& END-OF-SELECTION
*&---------------------------------------------------------------------*
END-OF-SELECTION.
*----------------------------------------------------------------------*
* Class implementation
*----------------------------------------------------------------------*
CLASS lcl_this IMPLEMENTATION.
  METHOD main.
*   Auth Check
    PERFORM frm_auth_check.

*   Get Billing data
    PERFORM frm_get_data.

*   Display HALV
    PERFORM frm_display_halv.
  ENDMETHOD.
ENDCLASS.
*&---------------------------------------------------------------------*
*& Form frm_auth_check
*&---------------------------------------------------------------------*
*& Auth Check
*&---------------------------------------------------------------------*
FORM frm_auth_check .

ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_get_data
*&---------------------------------------------------------------------*
*& Get Billing data
*&---------------------------------------------------------------------*
FORM frm_get_data .
  DATA:
    lt_invoices     TYPE tt_invoices,
    lt_item_price   TYPE tt_item_price,
    ls_alv          TYPE ty_alv,
    lv_index        TYPE i,
    ls_style        TYPE lvc_s_styl,
    lv_longtext_str TYPE string,
    lt_konp         TYPE tt_konp.

* Long text
  DATA:
    lt_text_i TYPE idmx_di_t_thead,
    ls_text_i TYPE thead,
    lt_text_e TYPE text_lh,
    lv_name   TYPE thead-tdname.

* Get Billing document
  SELECT a~vbeln,
         a~fkdat,
         c~kdmat,
         d~kunnr,
         a~vkorg,
         a~vtweg,
         b~vkbur,
         a~knumv,
         a~bukrs,
         a~belnr,
         a~gjahr,
         b~posnr,
         b~matnr,
         e~maktx,
         f~bismt,
         b~fkimg,
         b~vrkme,
         b~werks,
         b~aubel,
         b~aupos,
         CAST( a~vbeln AS CHAR( 30 ) ) AS objky
    INTO TABLE @lt_invoices
    FROM vbrk AS a
   INNER JOIN vbrp AS b
      ON a~vbeln = b~vbeln
   INNER JOIN vbap AS c
      ON b~aubel = c~vbeln
     AND b~aupos = c~posnr
   INNER JOIN vbpa AS d
      ON a~vbeln = d~vbeln
     AND d~posnr = 000000
     AND d~parvw = 'RE'
    LEFT OUTER JOIN makt AS e
      ON b~matnr = e~matnr
     AND e~spras = @sy-langu
    LEFT OUTER JOIN mara AS f
      ON b~matnr = f~matnr
   WHERE a~vbeln IN @s_vbeln
     AND a~fkdat IN @s_fkdat
     AND d~kunnr IN @s_kunre
     AND a~vkorg IN @s_vkorg
     AND a~vtweg IN @s_vtweg
     AND b~vkbur IN @s_vkbur
     AND c~kdmat IN @s_kdmat.

  IF lt_invoices IS NOT INITIAL.
    DATA(lt_copy) = lt_invoices.
    DELETE ADJACENT DUPLICATES FROM lt_copy COMPARING vbeln.

*   Get IDOC output info
    SELECT a~kappl,
           a~objky,
           a~kschl,
           a~spras,
           a~parnr,
           a~parvw,
           a~erdat,
           a~eruhr,
           a~nacha,
           a~vstat,
           a~tdcovtitle,
           a~cmfpnr,
           a~datvr,
           a~uhrvr,
           b~aplid,
           b~nr,
           b~msgcnt,
           b~arbgb,
           b~msgnr,
           b~msgv1,
           c~status
      INTO TABLE @DATA(lt_nast)
      FROM nast AS a
     INNER JOIN cmfp AS b
        ON a~cmfpnr = b~nr
       AND b~aplid = 'WFMC'
       AND b~arbgb = 'E0' AND b~msgnr = '045'
      LEFT OUTER JOIN edidc AS c
        ON b~msgv1 = c~docnum
       FOR ALL ENTRIES IN @lt_copy
     WHERE a~kappl = 'V3'
       AND a~objky = @lt_copy-objky
       AND a~kschl = 'RD00'
       AND a~spras = @sy-langu
       AND a~parnr = @lt_copy-kunnr
       AND a~parvw = 'RE'.

    DELETE ADJACENT DUPLICATES FROM lt_invoices
      COMPARING vbeln posnr aubel aupos.

    SORT lt_nast BY objky ASCENDING
                    erdat DESCENDING
                    eruhr DESCENDING.

*   If the Log button is not selected, only the latest records are retained
    IF p_log <> abap_on.
      DELETE ADJACENT DUPLICATES FROM lt_nast COMPARING objky.
    ENDIF.

*   Get Billing price
    SELECT knumv,
           kposn,
           stunr,
           zaehk,
           kappl,
           kschl,
           kbetr,
           waers,
           kpein,
           kmein
      INTO TABLE @DATA(lt_prcd_elements)
      FROM prcd_elements
       FOR ALL ENTRIES IN @lt_invoices
     WHERE knumv = @lt_invoices-knumv
       AND kposn = @lt_invoices-posnr
       AND kappl = 'V'
       AND kschl = 'PR00'.

    SORT lt_prcd_elements BY knumv ASCENDING
                             kposn ASCENDING.

*   Get sales condition price
    SELECT a~kappl,
           a~kschl,
           a~vkorg,
           a~vtweg,
           a~vkbur,
           a~kunnr,
           a~matnr,
           a~kfrst,
           a~datbi,
           a~datab,
           a~knumh,
           b~kopos,
           b~kbetr,
           b~konwa,
           b~kpein,
           b~kmein
      INTO TABLE @lt_konp
      FROM a996 AS a
     INNER JOIN konp AS b
        ON a~knumh = b~knumh
       FOR ALL ENTRIES IN @lt_invoices
     WHERE a~kappl =  'V'
       AND a~kschl =  'PR00'
       AND a~vkorg =  @lt_invoices-vkorg
       AND a~vtweg =  @lt_invoices-vtweg
       AND a~vkbur =  @lt_invoices-vkbur
       AND a~kunnr =  @lt_invoices-kunnr
       AND a~matnr =  @lt_invoices-matnr
       AND a~datab <= @lt_invoices-fkdat
       AND a~datbi >= @lt_invoices-fkdat.

    LOOP AT lt_invoices INTO DATA(ls_invoices).
      lv_name = ls_invoices-vbeln &&
                ls_invoices-posnr.

*     Manifast#
      ls_text_i-tdobject = 'VBBP'.
      ls_text_i-tdname   = lv_name.
      ls_text_i-tdid     = 'Z007'.
      ls_text_i-tdspras  = sy-langu.
      APPEND ls_text_i TO lt_text_i.
      CLEAR ls_text_i.

*     Kanban
      ls_text_i-tdobject = 'VBBP'.
      ls_text_i-tdname   = lv_name.
      ls_text_i-tdid     = '0002'.
      ls_text_i-tdspras  = sy-langu.
      APPEND ls_text_i TO lt_text_i.
      CLEAR ls_text_i.
    ENDLOOP.

*   Get multiple long text
    CALL FUNCTION 'READ_TEXT_TABLE'
*     EXPORTING
*       CLIENT_SPECIFIED              = ' '
*       ARCHIVE_HANDLE                = 0
*       LOCAL_CAT                     = ' '
      IMPORTING
        text_table              = lt_text_e
*       ERROR_TABLE             =
      TABLES
        text_headers            = lt_text_i
      EXCEPTIONS
        wrong_access_to_archive = 1
        OTHERS                  = 2.

    IF sy-subrc <> 0.
*     Implement suitable error handling here
    ENDIF.

    SORT lt_text_e BY header ASCENDING.
  ENDIF.


  LOOP AT lt_nast INTO DATA(ls_nast).
*   Get price from IDOC
    PERFORM frm_price_from_idoc USING ls_nast-msgv1
                             CHANGING lt_item_price.

*   Collect ALV data
    LOOP AT lt_invoices INTO ls_invoices WHERE vbeln = ls_nast-objky+0(10).
      ls_alv-docnum = ls_nast-msgv1.                                    "IDoc number
      ls_alv-datvr  = ls_nast-datvr.                                    "Processing date
      ls_alv-uhrvr  = ls_nast-uhrvr.                                    "Processing time
      ls_alv-status = ls_nast-status.                                   "Status of IDoc
      ls_alv-manual = xsdbool( ls_nast-tdcovtitle = 'ZPRMANUAL' ).      "Manual send flag

      ls_alv-vbeln = ls_invoices-vbeln.                                 "Billing Document
      ls_alv-fkdat = ls_invoices-fkdat.                                 "Billing Date
      ls_alv-kdmat = ls_invoices-kdmat.                                 "Customer Material
      ls_alv-kunre = ls_invoices-kunnr.                                 "Bill-to party
      ls_alv-vkorg = ls_invoices-vkorg.                                 "Sales Organization
      ls_alv-vtweg = ls_invoices-vtweg.                                 "Distribution Channel
      ls_alv-vkbur = ls_invoices-vkbur.                                 "Sales office
      ls_alv-bukrs = ls_invoices-bukrs.                                 "Company Code
      ls_alv-belnr = ls_invoices-belnr.                                 "Accounting Document Number
      ls_alv-gjahr = ls_invoices-gjahr.                                 "Fiscal Year
      ls_alv-posnr = ls_invoices-posnr.                                 "Billing Item
      ls_alv-matnr = ls_invoices-matnr.                                 "Material Number
      ls_alv-maktx = ls_invoices-maktx.                                 "Material Description
      ls_alv-bismt = ls_invoices-bismt.                                 "Old material number
      ls_alv-fkimg = ls_invoices-fkimg.                                 "Actual billed quantity
      ls_alv-vrkme = ls_invoices-vrkme.                                 "Sales unit
      ls_alv-werks = ls_invoices-werks.                                 "Plant

      READ TABLE lt_prcd_elements INTO DATA(ls_prcd_elements)
        WITH KEY knumv = ls_invoices-knumv
                 kposn = ls_invoices-posnr
                 BINARY SEARCH.
      IF sy-subrc = 0.
        ls_alv-invoice_price = ls_prcd_elements-kbetr.                  "Invoice Price
        ls_alv-waers         = ls_prcd_elements-waers.                  "Currency Key
        ls_alv-kpein         = ls_prcd_elements-kpein.                  "Condition Pricing Unit
        ls_alv-kmein         = ls_prcd_elements-kmein.                  "Condition Pricing Unit
      ENDIF.

      READ TABLE lt_item_price INTO DATA(ls_item_price)
        WITH KEY posex = ls_invoices-posnr BINARY SEARCH.
      IF sy-subrc = 0.
        ls_alv-idoc_price = ls_item_price-betrg.                        "IDoc Price
      ENDIF.

      LOOP AT lt_konp INTO DATA(ls_konp)
        WHERE vkorg =  ls_invoices-vkorg
          AND vtweg =  ls_invoices-vtweg
          AND vkbur =  ls_invoices-vkbur
          AND kunnr =  ls_invoices-kunnr
          AND matnr =  ls_invoices-matnr
          AND datab <= ls_invoices-fkdat
          AND datbi >= ls_invoices-fkdat.

        ls_alv-current_price = ls_konp-kbetr.                           "Current Price
        EXIT.
      ENDLOOP.

      ls_alv-diff_amount = ( ls_alv-current_price - ls_alv-invoice_price ) /
                             ls_alv-kpein *
                             ls_alv-fkimg.                              "Amount of variance

      lv_name = ls_alv-vbeln && ls_alv-posnr.

      READ TABLE lt_text_e INTO DATA(ls_text_e)
        WITH KEY header-tdobject = 'VBBP'
                 header-tdname   = lv_name
                 header-tdid     = 'Z007'.
      IF sy-subrc = 0.
        CLEAR lv_longtext_str.
        CALL FUNCTION 'IDMX_DI_TLINE_INTO_STRING'
          EXPORTING
            it_tline       = ls_text_e-lines
          IMPORTING
            ev_text_string = lv_longtext_str.

        ls_alv-manifast = lv_longtext_str.                              "Manifast
      ENDIF.

      READ TABLE lt_text_e INTO ls_text_e
        WITH KEY header-tdobject = 'VBBP'
                 header-tdname   = lv_name
                 header-tdid     = '0002'.
      IF sy-subrc = 0.
        CLEAR lv_longtext_str.
        CALL FUNCTION 'IDMX_DI_TLINE_INTO_STRING'
          EXPORTING
            it_tline       = ls_text_e-lines
          IMPORTING
            ev_text_string = lv_longtext_str.

        ls_alv-kanban = lv_longtext_str.                                "Kanban
      ENDIF.

      IF s_manif IS NOT INITIAL.
        IF ls_alv-manifast NOT IN s_manif.
          CLEAR ls_alv.
          CONTINUE.
        ENDIF.
      ENDIF.

      IF ( ls_alv-current_price - ls_alv-idoc_price ) = 0.
        ls_style-fieldname = gc_field_check.
        ls_style-style     = cl_gui_alv_grid=>mc_style_disabled.
        INSERT ls_style INTO TABLE ls_alv-style.
        CLEAR ls_style.
      ENDIF.

      ADD 1 TO lv_index.

      ls_alv-zindex = lv_index.                                         "Line index

      APPEND ls_alv TO gt_alv.

      CLEAR:
        ls_alv,
        lv_name,
        ls_prcd_elements,
        ls_item_price,
        ls_konp,
        ls_text_e,
        lv_longtext_str.
    ENDLOOP.

    CLEAR lt_item_price.
  ENDLOOP.

  IF gt_alv IS INITIAL.
*   No data meets the selection criteria.
    MESSAGE s048(zprbcmsg) DISPLAY LIKE 'E'.
    LEAVE LIST-PROCESSING.
  ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_display_halv
*&---------------------------------------------------------------------*
*& Show ALV
*&---------------------------------------------------------------------*
FORM frm_display_halv .
* Set layout
  gs_layout-zebra       = abap_true.
  gs_layout-cwidth_opt  = abap_true.
  gs_layout-no_rowmark  = abap_true.
  gs_layout-sel_mode    = gc_alv_sel_mode.
  gs_layout-stylefname  = gc_field_style.

  gs_event-name      = 'DATA_CHANGED'.
  gs_event-form      = 'FRM_ALV_DATA_CHANGED'.
  APPEND gs_event TO gt_event.

  gs_grid_settings-edt_cll_cb = abap_true.

* Get fieldcat
  CALL FUNCTION 'LVC_FIELDCATALOG_MERGE' ##FM_SUBRC_OK
    EXPORTING
      i_structure_name       = gc_key_ddic_alv
      i_bypassing_buffer     = abap_true
    CHANGING
      ct_fieldcat            = gt_fieldcat
    EXCEPTIONS
      inconsistent_interface = 1
      program_error          = 2
      OTHERS                 = 3.

* Hide index
  READ TABLE gt_fieldcat ASSIGNING FIELD-SYMBOL(<fs_fieldcat>)
    WITH KEY fieldname = gc_field_zindex.
  IF sy-subrc = 0.
    <fs_fieldcat>-tech = abap_true.
  ENDIF.

* Make checkbox editable
  READ TABLE gt_fieldcat ASSIGNING <fs_fieldcat>
    WITH KEY fieldname = gc_field_check.
  IF sy-subrc = 0.
    IF p_log = abap_on.
      <fs_fieldcat>-tech     = abap_true.
    ELSE.
      <fs_fieldcat>-checkbox = abap_true.
      <fs_fieldcat>-edit     = abap_true.
    ENDIF.
  ENDIF.

* Set hotspot event for IDoc number filed
  READ TABLE gt_fieldcat ASSIGNING <fs_fieldcat>
    WITH KEY fieldname = gc_field_docnum.
  IF sy-subrc = 0.
    <fs_fieldcat>-hotspot = abap_true.
  ENDIF.

* Set hotspot event for Billing number filed
  READ TABLE gt_fieldcat ASSIGNING <fs_fieldcat>
    WITH KEY fieldname = gc_field_vbeln.
  IF sy-subrc = 0.
    <fs_fieldcat>-hotspot = abap_true.
  ENDIF.

* When select "Display History",Hide some fileds
  IF p_log = abap_on.
    READ TABLE gt_fieldcat ASSIGNING <fs_fieldcat>
      WITH KEY fieldname = gc_field_icon.
    IF sy-subrc = 0.
      <fs_fieldcat>-tech = abap_true.
    ENDIF.

    READ TABLE gt_fieldcat ASSIGNING <fs_fieldcat>
      WITH KEY fieldname = gc_field_msg.
    IF sy-subrc = 0.
      <fs_fieldcat>-tech = abap_true.
    ENDIF.
  ENDIF.

* ALV display
  CALL FUNCTION 'REUSE_ALV_GRID_DISPLAY_LVC'
    EXPORTING
      i_callback_program       = syst-repid
      it_fieldcat_lvc          = gt_fieldcat
      i_callback_user_command  = 'FRM_USER_COMMAND'
      i_callback_pf_status_set = 'FRM_PF_STATUS_SET'
      is_layout_lvc            = gs_layout
      i_save                   = 'A'
      it_events                = gt_event
      i_grid_settings          = gs_grid_settings
    TABLES
      t_outtab                 = gt_alv
    EXCEPTIONS
      program_error            = 1
      OTHERS                   = 2.

  IF sy-subrc <> 0.
    MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
    WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
  ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_price_from_idoc
*&---------------------------------------------------------------------*
*& Get price from IDOC
*&---------------------------------------------------------------------*
*&      --> LS_NAST_MSGV1
*&      <-- LT_ITEM_PRICE
*&---------------------------------------------------------------------*
FORM frm_price_from_idoc  USING    uv_idoc_no TYPE cmfp-msgv1
                          CHANGING ct_item_price TYPE tt_item_price.
  DATA:
    ls_item_price TYPE ty_item_price,
    ls_e1edp01    TYPE e1edp01,
    ls_e1edp26    TYPE e1edp26.

  DATA:
    lv_idoc_number     TYPE edidc-docnum,
    ls_idoc_control    TYPE edidc,
    lt_idoc_containers TYPE STANDARD TABLE OF edidd.

  CHECK uv_idoc_no IS NOT INITIAL.

  lv_idoc_number = uv_idoc_no.

  CALL FUNCTION 'EDI_DOCUMENT_OPEN_FOR_PROCESS'
    EXPORTING
*     DB_READ_OPTION           = DB_READ
      document_number          = lv_idoc_number
*     ENQUEUE_OPTION           = SYNCHRONOUS
    IMPORTING
      idoc_control             = ls_idoc_control
    EXCEPTIONS
      document_foreign_lock    = 1
      document_not_exist       = 2
      document_number_invalid  = 3
      document_is_already_open = 4
      OTHERS                   = 5.

  IF sy-subrc <> 0.
*   Implement suitable error handling here
  ENDIF.

  CALL FUNCTION 'EDI_SEGMENTS_GET_ALL'
    EXPORTING
      document_number         = lv_idoc_number
    TABLES
      idoc_containers         = lt_idoc_containers
    EXCEPTIONS
      document_number_invalid = 1
      end_of_document         = 2
      OTHERS                  = 3.
  IF sy-subrc <> 0.
*   Implement suitable error handling here
  ENDIF.

  LOOP AT lt_idoc_containers INTO DATA(ls_idoc_containers).
    CASE ls_idoc_containers-segnam.
      WHEN 'E1EDP01'.
        IF ls_item_price IS NOT INITIAL.
          INSERT ls_item_price INTO TABLE ct_item_price.
          CLEAR ls_item_price.
        ENDIF.

        MOVE ls_idoc_containers-sdata TO ls_e1edp01.

        ls_item_price-posex = ls_e1edp01-posex.

      WHEN 'E1EDP26'.
        MOVE ls_idoc_containers-sdata TO ls_e1edp26.
        IF ls_e1edp26-qualf = '001'.
          ls_item_price-betrg = ls_e1edp26-betrg.
        ENDIF.
      WHEN OTHERS.
    ENDCASE.
  ENDLOOP.

  INSERT ls_item_price INTO TABLE ct_item_price.
  CLEAR ls_item_price.

  CALL FUNCTION 'EDI_DOCUMENT_CLOSE_PROCESS'
    EXPORTING
      document_number     = lv_idoc_number
*     BACKGROUND          = NO_BACKGROUND
*     NO_DEQUEUE          = ' '
*     STATUS_CHECK        = ' '
*     QRFC_STATE          = 'U'
*     P_EDIQI             =
*   IMPORTING
*     IDOC_CONTROL        =
    EXCEPTIONS
      document_not_open   = 1
      failure_in_db_write = 2
      parameter_error     = 3
      status_set_missing  = 4
      OTHERS              = 5.

  IF sy-subrc <> 0.
*   Implement suitable error handling here
  ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_alv_data_changed
*&---------------------------------------------------------------------*
*& Data changed event catch
*&---------------------------------------------------------------------*
FORM frm_alv_data_changed  USING er_data_changed TYPE REF TO cl_alv_changed_data_protocol.
  DATA:
    ls_good_cells TYPE lvc_s_modi,
    lo_grid       TYPE REF TO cl_gui_alv_grid,
    ls_stable     TYPE lvc_s_stbl,
    ls_layout     TYPE lvc_s_layo,
    lv_refresh    TYPE flag.

  CALL FUNCTION 'GET_GLOBALS_FROM_SLVC_FULLSCR'
    IMPORTING
      e_grid = lo_grid.

  LOOP AT er_data_changed->mt_good_cells INTO ls_good_cells.
    IF ls_good_cells-fieldname = gc_field_check AND
       ls_good_cells-value     = abap_true.

      lv_refresh = abap_true.

      READ TABLE gt_alv INTO DATA(ls_alv) INDEX ls_good_cells-row_id.

      LOOP AT gt_alv ASSIGNING FIELD-SYMBOL(<fs_alv>)
        WHERE vbeln = ls_alv-vbeln
          AND style IS INITIAL.

        IF <fs_alv>-checkbox <> abap_true.
          <fs_alv>-checkbox = abap_true.
        ENDIF.
      ENDLOOP.
    ENDIF.
  ENDLOOP.

  CHECK lv_refresh = abap_true.

  ls_stable-row = abap_true.
  ls_stable-col = abap_true.

* Refresh ALV
  CALL METHOD lo_grid->refresh_table_display
    EXPORTING
      is_stable = ls_stable
    EXCEPTIONS
      finished  = 1
      OTHERS    = 2.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_pf_status_set
*&---------------------------------------------------------------------*
*& Set status
*&---------------------------------------------------------------------*
FORM frm_pf_status_set USING rt_extab TYPE slis_t_extab.
  DATA ls_extab TYPE slis_extab.

  IF p_log = abap_on.
    ls_extab-fcode = gc_bt_selall.
    APPEND ls_extab TO rt_extab.

    ls_extab-fcode = gc_bt_desel.
    APPEND ls_extab TO rt_extab.

    ls_extab-fcode = gc_bt_resend.
    APPEND ls_extab TO rt_extab.
  ENDIF.

  SET PF-STATUS 'STATUS' EXCLUDING rt_extab.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_user_command
*&---------------------------------------------------------------------*
*& Process user command
*&---------------------------------------------------------------------*
FORM frm_user_command USING r_ucomm LIKE sy-ucomm
                            rs_selfield TYPE slis_selfield.
  DATA:
    lo_grid   TYPE REF TO cl_gui_alv_grid,
    ls_stable TYPE lvc_s_stbl,
    ls_layout TYPE lvc_s_layo.

  DATA:
    lo_control TYPE REF TO cl_gui_control,
    lt_control TYPE cnto_control_list.

  CALL FUNCTION 'GET_GLOBALS_FROM_SLVC_FULLSCR'
    IMPORTING
      e_grid = lo_grid.

  CALL METHOD lo_grid->check_changed_data.

  CASE r_ucomm.
*   Resend IDoc
    WHEN gc_bt_resend.
      PERFORM frm_resend_idoc.
*   Select all
    WHEN gc_bt_selall.
      PERFORM frm_choose_box USING abap_on.
*   Deselect all
    WHEN gc_bt_desel.
      PERFORM frm_choose_box USING abap_off.
*   Double click
    WHEN gc_double_click.
      PERFORM frm_double_click USING rs_selfield.
    WHEN OTHERS.
      BREAK-POINT.
  ENDCASE.

  CALL METHOD lo_grid->get_frontend_layout
    IMPORTING
      es_layout = ls_layout.

  ls_layout-cwidth_opt = abap_true.

* Set Optimize column width
  CALL METHOD lo_grid->set_frontend_layout
    EXPORTING
      is_layout = ls_layout.

  ls_stable-row = abap_true.
  ls_stable-col = abap_true.

* Refresh ALV
  CALL METHOD lo_grid->refresh_table_display
    EXPORTING
      is_stable = ls_stable
    EXCEPTIONS
      finished  = 1
      OTHERS    = 2.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_CHOOSE_BOX
*&---------------------------------------------------------------------*
*& Choose box
*&---------------------------------------------------------------------*
FORM frm_choose_box  USING uv_sel TYPE char1.
  LOOP AT gt_alv ASSIGNING FIELD-SYMBOL(<fs_alv>).
    IF uv_sel = abap_true.
      IF <fs_alv>-style IS INITIAL.
        <fs_alv>-checkbox = uv_sel.
      ENDIF.
    ELSE.
      <fs_alv>-checkbox = uv_sel.
    ENDIF.
  ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_resend_idoc
*&---------------------------------------------------------------------*
*& Resend IDoc
*&---------------------------------------------------------------------*
FORM frm_resend_idoc .
  DATA:
    lv_question TYPE string,
    lv_answer   TYPE char1.

  CLEAR gt_sel_alv.
  gt_sel_alv = gt_alv.
  DELETE gt_sel_alv WHERE checkbox = abap_false.

  IF gt_sel_alv IS INITIAL.
*   Please select the data first.
    MESSAGE s004(zprbcmsg) DISPLAY LIKE gc_msgty_e.
    RETURN.
  ELSE.
    READ TABLE gt_sel_alv TRANSPORTING NO FIELDS
      WITH KEY manual = abap_true.
    IF sy-subrc = 0.
      lv_question = |Some Updated EDI have already been sent, Do you want to Resend again?|.

      CALL FUNCTION 'POPUP_TO_CONFIRM'
        EXPORTING
          titlebar              = 'Confirm'
          text_question         = lv_question
          text_button_1         = 'Yes'
          text_button_2         = 'No'
          display_cancel_button = ''
        IMPORTING
          answer                = lv_answer
        EXCEPTIONS
          text_not_found        = 1
          OTHERS                = 2.

      IF sy-subrc <> 0.
*       Implement suitable error handling here
      ELSE.
        IF lv_answer <> '1'.
          MESSAGE 'User cancelled.' TYPE 'S'.
          RETURN.
        ENDIF.
      ENDIF.
    ENDIF.
  ENDIF.

* Execute resend IDoc
  PERFORM frm_execute_resend.

  LOOP AT gt_alv ASSIGNING FIELD-SYMBOL(<fs_alv>) WHERE checkbox = abap_true.
    READ TABLE gt_sel_alv INTO DATA(ls_sel_alv)
      WITH KEY vbeln = <fs_alv>-vbeln BINARY SEARCH.
    IF sy-subrc = 0.
      <fs_alv>-icon = ls_sel_alv-icon.
      <fs_alv>-msg  = ls_sel_alv-msg.
    ENDIF.
  ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_execute_resend
*&---------------------------------------------------------------------*
*& Execute resend IDoc
*&---------------------------------------------------------------------*
FORM frm_execute_resend .
* For create new output to Billing
  DATA:
    lt_nast TYPE STANDARD TABLE OF nast,
    ls_nast TYPE nast.

* For run VF31(custom report:zprsd70av3a - >copy from SE38:sd70av3a)
  DATA:
    rt_erdat TYPE RANGE OF nast-erdat,
    rt_eruhr TYPE RANGE OF nast-eruhr,
    rt_objky TYPE RANGE OF nast-objky,
    rt_kschl TYPE RANGE OF nast-kschl.

* For get VF31 process result
  DATA:
    msgs TYPE STANDARD TABLE OF msg0.

  SORT gt_sel_alv BY vbeln ASCENDING.
  DELETE ADJACENT DUPLICATES FROM gt_sel_alv COMPARING vbeln.

  LOOP AT gt_sel_alv ASSIGNING FIELD-SYMBOL(<fs_sel_alv>).
    ls_nast-kappl      = 'V3'.                                          "Application
    ls_nast-objky      = <fs_sel_alv>-vbeln.                            "Billing
    ls_nast-mandt      = sy-mandt.                                      "Client
    ls_nast-kschl      = 'RD00'.                                        "Message type
    ls_nast-spras      = sy-langu.                                      "Language
    ls_nast-parnr      = <fs_sel_alv>-kunre.                            "message partner
    ls_nast-parvw      = 'RE'.                                          "Partner Role
    ls_nast-objtype    = 'VBRK'.                                        "Object type
    ls_nast-tdcovtitle = 'ZPRMANUAL'.                                   "Manually flag
    ls_nast-nacha      = '6'.                                           "EDI
    ls_nast-vsztp      = '3'.                                           "Send immediately. Check domain values
    ls_nast-manue      = 'X'.                                           "Very important: message processed manually
    APPEND ls_nast TO lt_nast.

**********************************************************************
*   Step-1. test add output RD00 to VF02
**********************************************************************
    CALL FUNCTION 'RV_MESSAGES_INSERT'
*     EXPORTING
*       LV_ARCH         = ' '
      TABLES
        tab_xnast = lt_nast.

    CALL FUNCTION 'RV_MESSAGES_UPDATE'
      EXPORTING
        msg_kappl          = 'V3'
        msg_objky          = ls_nast-objky
        msg_no_update_task = 'X'.

    IF sy-subrc = 0.
      COMMIT WORK AND WAIT.

      ASSIGN ('(SAPLV61B)XNAST') TO FIELD-SYMBOL(<ls_xnast>).
    ELSE.
      ROLLBACK WORK.
      <fs_sel_alv>-icon = icon_led_red.
      <fs_sel_alv>-msg  = 'Add output failed!'.

      CLEAR:lt_nast.
      CONTINUE.
    ENDIF.

**********************************************************************
*   Step-2. test run VF31 and send immediately
**********************************************************************
    ASSIGN COMPONENT 'ERDAT' OF STRUCTURE <ls_xnast> TO FIELD-SYMBOL(<lv_erdat>).
    ASSIGN COMPONENT 'ERUHR' OF STRUCTURE <ls_xnast> TO FIELD-SYMBOL(<lv_eruhr>).

    rt_objky = VALUE #( ( sign = 'I' option = 'EQ' low = ls_nast-objky ) ).
    rt_kschl = VALUE #( ( sign = 'I' option = 'EQ' low = ls_nast-kschl ) ).
    rt_erdat = VALUE #( ( sign = 'I' option = 'EQ' low = <lv_erdat> ) ).
    rt_eruhr = VALUE #( ( sign = 'I' option = 'EQ' low = <lv_eruhr> ) ).

    SUBMIT zprsd70av3a
      WITH rg_kschl IN rt_kschl
      WITH rg_vbeln IN rt_objky
      WITH pm_verdi = abap_true
      WITH rg_erdat IN rt_erdat
      WITH rg_eruhr IN rt_eruhr
       AND RETURN.

**********************************************************************
*   Step-3. Get process result from VF31
**********************************************************************
    IMPORT msgs = msgs FROM MEMORY ID 'ZPRMEMORY_VF31'.
    FREE MEMORY ID 'ZPRMEMORY_VF31'.

    READ TABLE msgs INTO DATA(ls_msgs) INDEX 1.

*   Get process log
    SELECT aplid,
           nr,
           msgcnt,
           arbgb,
           msgnr,
           msgv1
      INTO TABLE @DATA(lt_cmfp)
      FROM cmfp
     WHERE aplid = 'WFMC'
       AND nr    = @ls_msgs-cmfpnr.

    SORT lt_cmfp BY msgnr ASCENDING.

    READ TABLE lt_cmfp INTO DATA(ls_cmfp)
      WITH KEY msgnr = '082' BINARY SEARCH.
    IF sy-subrc <> 0.
      READ TABLE lt_cmfp INTO ls_cmfp
        WITH KEY msgnr = '045' BINARY SEARCH.
    ENDIF.

    IF ls_cmfp IS INITIAL.
      <fs_sel_alv>-icon = icon_led_red.
      <fs_sel_alv>-msg  = 'IDoc send failed!'.
    ELSE.
      <fs_sel_alv>-icon = icon_led_green.

      MESSAGE ID ls_cmfp-arbgb
            TYPE gc_msgty_s
          NUMBER ls_cmfp-msgnr
            WITH ls_cmfp-msgv1
                 space
                 space
                 space
            INTO <fs_sel_alv>-msg.
    ENDIF.

    CLEAR:
      lt_nast,
      rt_objky,
      rt_kschl,
      rt_erdat,
      rt_eruhr,
      msgs,
      lt_cmfp.
  ENDLOOP.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form FRM_DOUBLE_CLICK
*&---------------------------------------------------------------------*
*& Hotspot event process
*&---------------------------------------------------------------------*
*&      --> US_SELFIELD
*&---------------------------------------------------------------------*
FORM frm_double_click  USING us_selfield TYPE slis_selfield.
  DATA:
    lv_docnum TYPE edidc-docnum,
    lv_vbeln  TYPE vbrk-vbeln.

* When IDoc
  IF us_selfield-fieldname = gc_field_docnum AND
     us_selfield-value IS NOT INITIAL.

    lv_docnum = us_selfield-value.

    SUBMIT idoc_tree_control WITH docnum = lv_docnum AND RETURN.
  ENDIF.

* When Billing number
  IF us_selfield-fieldname = gc_field_vbeln AND
     us_selfield-value IS NOT INITIAL.

    lv_vbeln = us_selfield-value.

    SET PARAMETER ID 'VF' FIELD lv_vbeln.

    CALL TRANSACTION 'VF03' AND SKIP FIRST SCREEN.
  ENDIF.
ENDFORM.
*&---------------------------------------------------------------------*
*& Form frm_initial_screen
*&---------------------------------------------------------------------*
*& Set default value
*&---------------------------------------------------------------------*
FORM frm_initial_screen .
  DATA:
    lv_datum_low TYPE datum.

  CALL FUNCTION 'RP_CALC_DATE_IN_INTERVAL'
    EXPORTING
      date      = sy-datlo
      days      = 0
      months    = 1
      signum    = '-'
      years     = 0
    IMPORTING
      calc_date = lv_datum_low.

  lv_datum_low+6(2) = '01'.

  s_fkdat-sign   = 'I'.
  s_fkdat-option = 'BT'.
  s_fkdat-low    = lv_datum_low.
  s_fkdat-high   = sy-datlo.
  APPEND s_fkdat.

ENDFORM.

  • 6
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DeveloperMrMeng

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值