piatok 1. júna 2012

Display customer fields in logistic invoice (MM) header


This article was inspired by Pablo Casamayor article Display customer fields in header of logistics invoice verification transactions.

Personally, when I tried to solve my problem of displaying customer fields in logistic invoice, I followed the article mentioned above.Thanks to Pablo's contribution I was able to succeed and now I would like to memorize all the necessary steps for enhancing logistic invoice head data, so that I can follow the in the future, when the need arrives.

First let's see what we are trying to accomplish. Our goal is to display two customer fields in header of logistic invoice. We will be also developing a match-code (F4) for these fields and this match-code will also consider a vendor number filled in invoice header. Several parts on the print-screens provided may be grayed out for personal reasons.

  1. As a first step, it is necessary to append our customer fields in relevant SAP standard tables and structures.
    Structure INVFO: (Display Structure for Contract Account Line Items) - screen fields.
    View: RBKP_V: (Incoming Invoice, Header Data) - invoice header data.
    Table: RBKP: (Document Header: Invoice Receipt) - invoice header data.
    Structure: ACMM_VENDOR_COMP (Vendor Dialog Component Interface FI-MM).
    Appending new fields in the above structures is necessary for storing the values in MM vendor invoice document.
    To store the customer fields as well in FI document, FI tables BKPF/BSEG must be appended with customer fields and a certain programming is necessary. This will be discussed in another blog in the future.

    Look at the dB RBKP:


    Look at view RBKP_V:


    Look at structure ACMM_VENDOR_COMP:

    Structure INVFO:
  2. BAdI used to include customer fields in logistic invoice is BADI_FDCB_SUBBAS04 (Screen Enhancement 4 on FDCB Basic Data Screen (010, 510)). Screen number 010 is used for Vendor Data. Screen number 510 is used for Customer Data.
    There is also default implementation class CL_DEF_IM_BADI_FDCB_SUBBAS04 and example implementation class CL_EXM_IM_BADI_FDCB_SUBBAS04. You might as well look at those.
    Obviously the next step is to create an implementation of BAdI BADI_FDCB_SUBBAS04.

    Therefore start transaction SE19 BAdI Builder and create your implementation.


    The source code of implemented methods may look like this:
    Method PUT_DATA_TO_SCREEN_OBJECT
    method IF_EX_BADI_FDCB_SUBBAS04~PUT_DATA_TO_SCREEN_OBJECT.
    * importing parameter IM_INVFO TYPE INFO
    * fill interface attributes from importing paramters

      me->if_ex_badi_fdcb_subbas04~invfo  = im_invfo.
    endmethod.


    Method GET_DATA_FROM_SCREEN_OBJECT
    METHOD if_ex_badi_fdcb_subbas04~get_data_from_screen_object.
    * exporting parameter EX_INVFO TYPE INVFO
    **********************************************************************

      
    DATA:
            l_ozzml 
    TYPE /ppask/mm_dodzml-/ppask/ozzml.
    **********************************************************************
    **********************************************************************
    *--> Store value in local variable:
      
    CLEAR: l_ozzml.
      l_ozzml = ex_invfo-zz_ozzml.

    * fill export parameters from interface attributes
      ex_invfo  = me->if_ex_badi_fdcb_subbas04~invfo.

    *--> If value in exporting parameter <> value in local *>>> variable, update exporting parameter with local value
      
    IF ( l_ozzml <> ex_invfo-zz_ozzml ) AND
         ( 
    NOT l_ozzml IS INITIAL )       AND
         ( ex_invfo-zz_ozzml 
    IS INITIAL ).
        ex_invfo-zz_ozzml = l_ozzml.
      
    ENDIF.
    ENDMETHOD.


    Another essential thing is to create a custom dynpro where our customer fields will be included and we will be able to find them in relevant transactions. Look at the Subscreens tab in the implemented BAdI.

    Look at the program ...SAPLMM_FDCB_BAS04 and dynpro 100. Our program is a function group.

    Dynpro Attributes:


    Dynpro Layout:

    Dynpro Flow logic:PROCESS BEFORE OUTPUT.
    * MODULE STATUS_0100.
      
    MODULE modify_screen_0100.
      
    MODULE receive_data.

    PROCESS AFTER 
    INPUT.
    * get again actual data from main screen
      
    MODULE receive_actual_data.

      
    FIELD:
       invfo-ZZ_OZZML,
       invfo-ZZ_ZMTXT.

    * send data back to main screen
      
    MODULE USER_COMMAND_0100.

    PROCESS 
    ON VALUE-REQUEST.
    * F4 help for a field ZZ_ZMTXT:
      
    FIELD:
        invfo-zz_zmtxt
        
    MODULE help_zz_zmtxt.


    Dynpro PROCESS_BEFORE_OUTPUT:
    *&---------------------------------------------------------------------*
    *&      Module  MODIFY_SCREEN_0100  OUTPUT
    *&---------------------------------------------------------------------*
    *       text
    *----------------------------------------------------------------------*
    MODULE modify_screen_0100 OUTPUT.
      
    PERFORM screen_modify_0100.
    ENDMODULE.                 " MODIFY_SCREEN_0100  OUTPUT

    *&---------------------------------------------------------------------*
    *&      Module  receive_data  OUTPUT
    *&---------------------------------------------------------------------*
    *       text
    *----------------------------------------------------------------------*
    MODULE receive_data OUTPUT.

      
    IF o_badi_fdcb_subbas04 IS INITIAL.

        
    CALL METHOD cl_exithandler=>get_instance_for_subscreens
          
    CHANGING
            instance                      = o_badi_fdcb_subbas04
          
    EXCEPTIONS
            no_reference                  = 
    1
            no_interface_reference        = 
    2
            no_exit_interface             = 
    3
            data_incons_in_exit_managem   = 
    4
            class_not_implement_interface = 
    5
            
    OTHERS                        = 6.
        
    IF sy-subrc <> 0.
    * MESSAGE ID SY-MSGID TYPE SY-MSGTY NUMBER SY-MSGNO
    *            WITH SY-MSGV1 SY-MSGV2 SY-MSGV3 SY-MSGV4.
        
    ENDIF.

      
    ENDIF.

    * object created  ?
      
    CHECK NOT o_badi_fdcb_subbas04 IS INITIAL.

    * get data from main screen

      
    CALL METHOD o_badi_fdcb_subbas04->get_data_from_screen_object
        
    IMPORTING
          ex_invfo = invfo.

    ENDMODULE.                 " receive_data  OUTPUT


    Dynpro PROCESS_AFTER_INPUT:
    *&---------------------------------------------------------------------*
    *&      Module  receive_actual_data  INPUT
    *&---------------------------------------------------------------------*
    *       text
    *----------------------------------------------------------------------*
    module receive_actual_data input.

    *  object created  ?
      
    CHECK NOT o_badi_fdcb_subbas04 IS INITIAL.

    * get data from main screen
      
    CALL METHOD o_badi_fdcb_subbas04->get_data_from_screen_object
        
    IMPORTING
          ex_invfo  = invfo.


    endmodule.                 " receive_actual_data  INPUT

    *&---------------------------------------------------------------------*
    *&      Module  USER_COMMAND_0100  INPUT
    *&---------------------------------------------------------------------*
    *       text
    *----------------------------------------------------------------------*
    module USER_COMMAND_0100 input.

     
    CHECK NOT o_badi_fdcb_subbas04 IS INITIAL.

    * put data to main screen
      
    CALL METHOD o_badi_fdcb_subbas04->put_data_to_screen_object
        
    EXPORTING
          im_invfo  = invfo.

    endmodule.                 " USER_COMMAND_0100  INPUT


    Dynpro PROCESS ON VALUE-REQUEST:
    *&---------------------------------------------------------------------*
    *&      Module  HELP_ZZ_ZMTXT  INPUT
    *&---------------------------------------------------------------------*
    *       text
    *----------------------------------------------------------------------*
    MODULE help_zz_zmtxt INPUT.
    *--> Search-Help for field zz_zmtxt:
      
    PERFORM f4_zz_zmtxt.
    ENDMODULE.                 " HELP_ZZ_ZMTXT  INPUT
    *&---------------------------------------------------------------------*
    *&      Form  F4_ZZ_ZMTXT
    *&---------------------------------------------------------------------*
    *       text
    *----------------------------------------------------------------------*
    *  -->  p1        text
    *  <--  p2        text
    *----------------------------------------------------------------------*
    FORM f4_zz_zmtxt .
    **********************************************************************
      
    TYPES:
        
    BEGIN OF t_dodzml, "table
          ozzml 
    TYPE /.../mm_dodzml-/ppask/ozzml,
          lifnr 
    TYPE /.../mm_dodzml-/ppask/lifnr, 
          datum 
    TYPE /.../mm_dodzml-/ppask/datum, 
          lftxt 
    TYPE /.../mm_dodzml-/ppask/lftxt, 
          zmtxt 
    TYPE /.../mm_dodzml-/ppask/zmtxt, 
        
    END   OF t_dodzml,
        ti_dodzml 
    TYPE STANDARD TABLE OF t_dodzml.
    **********************************************************************
      
    DATA:
            l_repid 
    TYPE sy-repid, 
            l_dynnr 
    TYPE sy-dynnr, 
            l_subrc 
    TYPE sy-subrc, 
            l_lifre 
    TYPE invfo-lifre, 
            lr_lifre 
    TYPE RANGE OF invfo-lifre, 
            ls_lifre 
    LIKE LINE OF lr_lifre,
            li_dodzml 
    TYPE ti_dodzml, 
            li_dynpflds 
    TYPE STANDARD TABLE OF dselc, 
            ls_dynpflds 
    LIKE LINE OF li_dynpflds,
            li_return 
    TYPE STANDARD TABLE OF ddshretval, 
            ls_return 
    LIKE LINE OF li_return.
    **********************************************************************
    *--> Initialize variables.
      
    CLEAR: l_repid,
             l_dynnr.
      l_repid = sy-repid.
      l_dynnr = sy-dynnr.

    *--> Selection screen for specifying hit list.:
      
    CLEAR: l_lifre.
      l_lifre = invfo-lifre.

    *>>> Do we have an entry in dB /.../mm_dodzml for a vendor?
      
    CLEAR l_subrc.
      
    SELECT SINGLE /ppask/lifnr
        
    INTO (l_lifre)
        
    FROM /.../mm_dodzml
        
    WHERE /ppask/lifnr = l_lifre.
      l_subrc = sy-subrc. 

      
    CASE l_subrc.  "were date read
        
    WHEN 0.      "data read -> filter hit-list based on vendor
          
    REFRESH lr_lifre.
          
    CLEAR ls_lifre.
          
    IF NOT l_lifre IS INITIAL.
            ls_lifre-
    sign = 'I'
            ls_lifre-option = 
    'EQ'
            ls_lifre-low = l_lifre. 
            
    APPEND ls_lifre TO lr_lifre.
          
    ENDIF.
        
    WHEN OTHERS"data not read -> do not filter hit-list
          
    REFRESH lr_lifre.
      
    ENDCASE.

    *--> Read table:
      
    REFRESH: li_dodzml.
      
    SELECT /.../ozzml AS ozzml /.../lifnr AS lifnr
             /.../datum 
    AS datum /.../lftxt AS lftxt
             /.../zmtxt 
    AS zmtxt
        
    INTO CORRESPONDING FIELDS OF TABLE li_dodzml
        
    FROM /.../mm_dodzml
        
    WHERE /.../lifnr IN lr_lifre.

    *--> Continue if data were read:
      
    CHECK sy-subrc = 0.

    *--> Show hit-list:
    *>>> Map dynpro fields:
      
    REFRESH: li_dynpflds.
      
    CLEAR ls_dynpflds.
      ls_dynpflds-fldname = 
    'F0001'.
      ls_dynpflds-dyfldname = 
    'INVFO-ZZ_OZZML'.
      
    APPEND ls_dynpflds TO li_dynpflds.

      
    CALL FUNCTION 'F4IF_INT_TABLE_VALUE_REQUEST'
        
    EXPORTING
          retfield        = 
    'ZMTXT'
          dynpprog        = l_repid
          dynpnr          = l_dynnr
          dynprofield     = 
    'INVFO-ZZ_ZMTXT'
          value_org       = 
    'S' "data structured in hit-list
        
    TABLES
          value_tab       = li_dodzml
          return_tab      = li_return
          dynpfld_mapping = li_dynpflds
        
    EXCEPTIONS
          parameter_error = 
    1
          no_values_found = 
    2
          
    OTHERS          = 3.

      
    IF sy-subrc <> 0.
        
    MESSAGE ID sy-msgid TYPE 'S' NUMBER sy-msgno
          
    WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
      
    ENDIF.
    ENDFORM.                    " F4_ZZ_ZMTXT