Thursday, 12 January 2017

Add a Custom Screen on Purchase Requisition Header By Replacing Standard GUI Status

I had saw some threads/posts in SAP forums, they were asking for the solutions on how to adding a custom screen/tab on the purchase requisition. But just as my knowledge, SAP has not provided any user-exit/Badi/SMOD for enhancing the screen of header part of purchase requisition.

And as we also know, purchase requisition database designing is different from other businesses object documents. A general designing of database table for business documents should commonly have Header and Items, some has Schedule Lines. For example, EKKO and EKPO for purchase order, VBAK and VBAP for sales order, BKPF and BSEG for FI documents……
For purchase requisition, it seems that the data is stored on item level, we only have EBAN for purchase requisition (other database table is not taken into account in this blog, for example account assignment table EBKN).

No standard enhancement and even no database design for purchase requisition header. Well, it seems that it is not possible to adding a custom screen for purchase requisition header level.

Some years ago we really cannot do it unless we put lots of effort on changing standard program. Of course this approach is hardly acceptable.

So, in case of receiving a requirement on making a custom header for purchase requisition or adding a new screen on header level, generally we will take an alternative solution, for example, add a custom screen tab on purchase item level, users can input header data on item level and the data should be item-dependent or item-independent, or even design a new application program to achieve the requirements.

But now, thanks for the new generation of enhancement technique, we can achieve the requirement by the implicit enhancement, and plus some SMOD/CMOD enhancement and Badi.

In this document, I would like to share a solution on how to make a custom header for purchase requisition. We will have many solutions for one requirement, and my idea is:

  • Design a custom database table for storing purchase requisition header data, table name is ZEBAN_HEADER
  • Add a new button on the application toolbar on ME51N/ME52N/ME53N/ME54N, the button text is Custom Header (I think this is the core point of the whole solution)
  • If users click the Custom Header button, a dialog box screen is popup, the screen title is CUSTOM PR HEADER FIELDS. And users can input data onto the screen
  • If user save the purchase requisition, the data she/he input on popup CUSTOM PR HEADER FIELDS screen are also saved into the custom table ZEBAN_HEADER

The result of the idea is we have an enhancement function for purchase requisition, but I hope the idea can also provide us a new thinking for other similar enhancement requirements.

1.  A glance and investigation on purchase requisition application

As everyone knows, the transactions for purchase requisition generally include ME51N, ME52N, ME53N, ME54N. For these transactions, the triggered program is RM_MEREQ_GUI (See SE93).

Add a Custom Screen on Purchase Requisition Header By Replacing Standard GUI Status

In source code of triggered program RM_MEREQ_GUI, the function module MEGUI_MAINTAIN is invoked. This function module is a component of function group MEGUI (User interface for purchasing document). As the description of MEGUI, all the components related to user interface of purchasing documents are integrated into/by this function group, for example, screens, GUI statuses (In my opinion,  MEGUI is just like the View of MVC pattern).

For the purchase requisition application, the main screen is 0014 of program SAPLMEGUI (or function group MEGUI), and GUI Status is REQ of program SAPLMEGUI (or function group MEGUI).

Add a Custom Screen on Purchase Requisition Header By Replacing Standard GUI Status

Add a Custom Screen on Purchase Requisition Header By Replacing Standard GUI Status


I investigate the application running by debugging, I found the application GUI Status is set in method PBO of class CL_WINDOW_MM (Inheriting from class CL_COMPOSITE_SCREEN_VIEW_MM), and the GUI Status is determined by method EXCLUDING_FUNCTIONS. The attributes DYNPRO and PROG indicate the current screen and program.

Add a Custom Screen on Purchase Requisition Header By Replacing Standard GUI Status

Add a Custom Screen on Purchase Requisition Header By Replacing Standard GUI Status

Add a Custom Screen on Purchase Requisition Header By Replacing Standard GUI Status

OK, I believe some people have got my thinking now.

Yes, we can develop a new custom program and insert a GUI Status as the program component, and we also add a new button, saying Custom Header, into the Application Toolbar of the GUI Status. Then we can replace the original standard GUI status (l_pfstatus) and its program (l_pfprogram) by our custom objects. The best replacing position, of cause, should be located at the end of method EXCLUDING_FUNCTIONS, and everyone knows we can do it by implicit enhancement.

It is better to copy the standard GUI Status REQ to our new custom GUI Status, so that we can preserve the original buttons and menus (Actually, this is very important. Otherwise we will lose lots of functionalities when processing a purchase requisition).

Now, a new button (Custom Header) is ready for purchase requisition application. But don’t forget that application program needs to response the new button.

By debugging, I found there have a method IF_COMMAND_MM~EXECUTE of local class LCL_DOCUMENT_CMD in function group MEGUI, which is the responder of users’ command.

Add a Custom Screen on Purchase Requisition Header By Replacing Standard GUI Status

Thanks the new generation enhancement technique again, we can place an implicit enhancement at the end of this method, so that the program can response the user command.

Beside the function group MEGUI, there has a function group MEREQ inside the whole application. This function group plays the role of processing purchase requisition document; it just looks like the Model of MVC pattern. There have lots of local classes in this function group; I would like to mention two local classes, which are involved in my document.

The local class LCL_REQ_HEADER is the model of purchase requisition header; it contains the processing logic on purchase requisition header. And another local class LCL_INSTANCE_FACTORY, a factory class for purchase requisition, is used for handling the core functionalities of purchase requisition, for example, post.

Of cause, we also have SMOD/Badi enhancements for processing purchase requisition; some of them will be involved in my document.

2. An enhancement demo step-by-step

My demo business requirement is: Users need to link a sales document with the purchase requisition in the header level. Below are my steps on the enhancement.

2.1 Step 1 – Create a Database table for custom header of purchase requisition:

Create a new database table in SE11 ABAP dictionary. In my case, the database table is ZEBAN_HEADER.

Add a Custom Screen on Purchase Requisition Header By Replacing Standard GUI Status

2.2 Step 2 – Create a function group as the core processing logic of the enhancement, and at the meantime, it also provides the role of container of GUI Status and custom header screen.

In my case, the function group is ZME51N_HEADER_ENHM. Below is the code of the TOP INCLUDE.

Add a Custom Screen on Purchase Requisition Header By Replacing Standard GUI Status

FUNCTION-POOL zme51n_header_enhm.           "MESSAGE-ID ..
TABLES: zeban_header.
DATA: okcode TYPE syucomm,
      main_okcode TYPE syucomm. "OKCODE FROM PR APPLICATION
DATA: gs_header_backup TYPE zeban_header.
DATA: g_original_changed_flag TYPE flag.
DATA: g_trtyp type trtyp. "H = Create, V = Change, A = Display
* INCLUDE LZME51N_HEADER_ENHMD...            " Local class definition

2.3  Step 3 – Create a GUI Status for replacing the original standard GUI status REQ of SAPLMEGUI. And do not forget to copy/adjust the buttons from standard GUI status REQ of SAPLMEGUI.

Add a Custom Screen on Purchase Requisition Header By Replacing Standard GUI Status

Add a Custom Screen on Purchase Requisition Header By Replacing Standard GUI Status

Add a Custom Screen on Purchase Requisition Header By Replacing Standard GUI Status

Add a Custom Screen on Purchase Requisition Header By Replacing Standard GUI Status

After adjusting the new GUI Status REQ from standard GUI Status REQ of SAPLMEGUI, we need to add a new button into the application toolbar, so that we can develop the logic for generating the custom header screen. In my case, the function code of new button is ZCUSTOM, and also input the related icon text and preferred icon name.

Add a Custom Screen on Purchase Requisition Header By Replacing Standard GUI Status

2.4 Step 4 – Create a dialog box screen for custom header of purchase requisition.

I would not demonstrate the screen creation in detail, since it is just a common development technique. And do not forget to create a dialog box GUI Status and title for this new screen.

Add a Custom Screen on Purchase Requisition Header By Replacing Standard GUI Status

Add a Custom Screen on Purchase Requisition Header By Replacing Standard GUI Status

Add a Custom Screen on Purchase Requisition Header By Replacing Standard GUI Status

PROCESS BEFORE OUTPUT.
 MODULE STATUS_0001.
*
PROCESS AFTER INPUT.
 MODULE USER_COMMAND_0001.

Add a Custom Screen on Purchase Requisition Header By Replacing Standard GUI Status

*----------------------------------------------------------------------*
***INCLUDE LZME51N_HEADER_ENHMO01.
*----------------------------------------------------------------------*
*&---------------------------------------------------------------------*
*&      Module  STATUS_0001  OUTPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
MODULE status_0001 OUTPUT.
  SET PF-STATUS 'CUSTOM_DYN'.
  SET TITLEBAR 'CUSTOM_DYN_TITLE'.
  LOOP AT SCREEN.
    IF screen-name = 'ZEBAN_HEADER-VBELN'.
      IF g_trtyp = 'A'.
*  display mode, input not possible
        screen-input = '0'.
      ELSE.
*  change or create mode, input activated
        screen-input = '1'.
      ENDIF.
    ENDIF.
    MODIFY SCREEN.
  ENDLOOP.
ENDMODULE.                 " STATUS_0001  OUTPUT

Add a Custom Screen on Purchase Requisition Header By Replacing Standard GUI Status

*----------------------------------------------------------------------*
***INCLUDE LZME51N_HEADER_ENHMI01.
*----------------------------------------------------------------------*
*&---------------------------------------------------------------------*
*&      Module  USER_COMMAND_0001  INPUT
*&---------------------------------------------------------------------*
*       text
*----------------------------------------------------------------------*
MODULE user_command_0001 INPUT.
  CASE okcode.
    WHEN 'OK'.
      GS_HEADER_BACKUP = ZEBAN_HEADER.
    WHEN 'EXIT'.
      ZEBAN_HEADER = GS_HEADER_BACKUP.
  ENDCASE.

  SET SCREEN 0.
  LEAVE SCREEN.
ENDMODULE.                 " USER_COMMAND_0001  INPUT

In my case, the dialog box GUI Status for the screen 0001 is CUSTOM_DYN, and the GUI title is CUSTOM_DYN_TITLE.

Add a Custom Screen on Purchase Requisition Header By Replacing Standard GUI Status

Add a Custom Screen on Purchase Requisition Header By Replacing Standard GUI Status

2.5 Step 5 – Insert below function modules into the function group ZME51N_HEADER_ENHM.

Add a Custom Screen on Purchase Requisition Header By Replacing Standard GUI Status

FUNCTION zpr_check_transaction_state .
*"----------------------------------------------------------------------
*"  IMPORTING
*"     REFERENCE(IM_BANFN) TYPE  BANFN
*"  CHANGING
*"     REFERENCE(CH_CHANGED) TYPE  FLAG OPTIONAL
*"----------------------------------------------------------------------
  DATA: l_count TYPE i.
  DATA: ls_custom_header TYPE zeban_header.
  g_original_changed_flag = ch_changed. "backup the original 'changed' indicator
  CHECK ch_changed IS INITIAL.
  SELECT COUNT( * ) INTO l_count FROM eban
         WHERE banfn = im_banfn.
  CHECK l_count >= 1.
*THE PROCESSED PR IS EXISTED IN DB
  SELECT SINGLE * INTO ls_custom_header
         FROM zeban_header
         WHERE banfn = im_banfn.
  IF ls_custom_header-vbeln <> zeban_header-vbeln.
*  THE CUSTOM FIELDS IN RUNTIME IS DIFFERENT FROM DB
*  THE PR HAS BEEN CHANGED
    ch_changed = 'X'.
  ENDIF.
ENDFUNCTION.


FUNCTION ZPR_EXPORT_BUFFER.
*"----------------------------------------------------------------------
*"  EXPORTING
*"     REFERENCE(EX_BANFN) TYPE  BANFN
*"     REFERENCE(EX_ORIGINAL_CHANGED) TYPE  FLAG
*"----------------------------------------------------------------------
ex_banfn = ZEBAN_HEADER-banfn.
EX_ORIGINAL_CHANGED = g_original_changed_flag.
clear g_original_changed_flag.
ENDFUNCTION.


FUNCTION zpr_header_custom_save.
*"----------------------------------------------------------------------
*"
*"  IMPORTING
*"     VALUE(IM_BANFN) TYPE  BANFN
*"----------------------------------------------------------------------
DATA: l_changed TYPE flag.
  DATA: l_count TYPE i.

  SELECT COUNT( * ) INTO l_count
         FROM eban
         WHERE banfn = im_banfn.
  IF l_count >= 1.
*    not create mode
*    we need to check if data has been changed
    CALL FUNCTION 'ZPR_CHECK_TRANSACTION_STATE'
      EXPORTING
        im_banfn   = im_banfn
      CHANGING
        ch_changed = l_changed.

    CHECK l_changed IS NOT INITIAL.
  ENDIF.

  zeban_header-banfn = im_banfn.

  CALL FUNCTION 'ZPR_HEADER_CUSTOM_SAVE_CORE' IN UPDATE TASK
    EXPORTING
      im_s_header = zeban_header.
ENDFUNCTION.


FUNCTION zpr_header_custom_save_core.
*"----------------------------------------------------------------------
*"
*"  IMPORTING
*"     VALUE(IM_S_HEADER) TYPE  ZEBAN_HEADER
*"----------------------------------------------------------------------
*please set the function module as Update Module
MODIFY zeban_header FROM IM_S_HEADER.
ENDFUNCTION.

FUNCTION zpr_header_custom_screen_call.
*"----------------------------------------------------------------------
*"  IMPORTING
*"     REFERENCE(IM_O_MODEL) TYPE REF TO  IF_MODEL_MM
*"     REFERENCE(IM_TRTYP) TYPE  TRTYP
*"----------------------------------------------------------------------
  DATA: l_changed TYPE flag.
  DATA: lo_processing_req TYPE REF TO if_purchase_requisition.
  lo_processing_req ?= im_o_model.
  g_trtyp = im_trtyp.
  CHECK lo_processing_req IS BOUND.
  lo_processing_req->get_transaction_state(
        IMPORTING
          ex_changed = l_changed ).
  IF g_trtyp = 'H' AND
    l_changed = space.
*create mode but no data is inputted
*a blank purchase requisition
    MESSAGE 'Please input the PR data first......' TYPE 'S' DISPLAY LIKE 'E'.
    EXIT.
  ENDIF.
  main_okcode = sy-ucomm.
  gs_header_backup = zeban_header.
  CALL SCREEN '0001' STARTING AT 25 6
                     ENDING AT 88 10.
  sy-ucomm = main_okcode.
ENDFUNCTION.


FUNCTION zpr_open.
*"----------------------------------------------------------------------
*"  IMPORTING
*"     REFERENCE(IO_HEADER) TYPE REF TO  IF_PURCHASE_REQUISITION
*"----------------------------------------------------------------------
  DATA: ls_header TYPE mereq_header.
  DATA: l_count TYPE i.
  CLEAR zeban_header.
  clear g_original_changed_flag.
  ls_header = io_header->get_data( ).
  SELECT COUNT( * ) INTO l_count FROM eban
         WHERE banfn = ls_header-banfn.
  CHECK l_count >= 1.
*THE PROCESSED PR IS EXISTED IN DB
  SELECT SINGLE * FROM zeban_header
        WHERE banfn = ls_header-banfn.
  IF sy-subrc <> 0.
    zeban_header-banfn = ls_header-banfn.
  ENDIF.
ENDFUNCTION.


FUNCTION ZPR_RESET_CHANGED_INDICATOR.
*"----------------------------------------------------------------------
*"  CHANGING
*"     REFERENCE(CH_CHANGED) TYPE  FLAG
*"----------------------------------------------------------------------
ch_changed = g_original_changed_flag.
clear g_original_changed_flag.
ENDFUNCTION.

2.6  Step 6 – Apply implicit enhancement implementation to replace the original standard GUI Status REQ of program SAPLMEGUI

Add a Custom Screen on Purchase Requisition Header By Replacing Standard GUI Status

ENHANCEMENT 1  ZME51N_TEST.    "active version
IF   sy-uname = 'CHENGANGRONG' AND
      sy-dynnr = '0014' AND
      ( sy-tcode = 'ME51N' OR
      sy-tcode = 'ME52N' OR
      sy-tcode = 'ME53N' OR
      sy-tcode = 'ME54N' ).
  IF dynpro = '0014' AND
     prog = 'SAPLMEGUI'.
    ch_pfprogram = 'SAPLZME51N_HEADER_ENHM'.
    ch_pfstatus = 'REQ'.
  ENDIF.
ENDIF.
ENDENHANCEMENT.

Once we have above implementation, a new button will appear on the application tool bar of purchase requisition applications (ME51N/ME52N/ME53N/ME54N).

Add a Custom Screen on Purchase Requisition Header By Replacing Standard GUI Status

2.7 Step 7 – make the Custom Header button functioning.

The method if_command_mm~execute of local class lcl_document_cmd of program SAPLMEGUI will response the user actions. We can put an implicit enhancement at the end of this method, so that the program can response the user command on the main screen of purchase requisition.

In my demo case, if user click Custom Header button, then program will call a dialog box screen 0001 in the enhancement function group ZME51N_HEADER_ENHM.

At the implementation section of if_command_mm~execute of local class lcl_document_cmd(locate at INCLUDE program LMEGUICJL), I put below implicit enhancement at the end of the method:

Add a Custom Screen on Purchase Requisition Header By Replacing Standard GUI Status

ENHANCEMENT 1  ZME51N_TEST2.    "active version
  DATA: ls_zzenhm_doc_info TYPE mepo_document,
        lt_zzenhm_doc_info TYPE mepo_documents,
        l_zzenhm_model type ref to if_model_mm.
  CHECK sy-uname = 'CHENGANGRONG' AND
        sy-dynnr = '0014' AND
        ( sy-tcode = 'ME51N' OR
        sy-tcode = 'ME52N' OR
        sy-tcode = 'ME53N' OR
        sy-tcode = 'ME54N' ).
  IF l_transaction IS NOT BOUND.
    l_transaction = l_appl->my_trmgr->get_current( ).
    CHECK l_transaction IS BOUND.
  ENDIF.
  l_transaction->get_info(
           IMPORTING
              ex_documents = lt_zzenhm_doc_info
              ex_aggregate = l_zzenhm_model ).
  READ TABLE lt_zzenhm_doc_info INTO ls_zzenhm_doc_info INDEX 1.
  CHECK sy-subrc = 0.
  CASE im_fcode.
    WHEN 'ZCUSTOM'.
      CALL FUNCTION 'ZPR_HEADER_CUSTOM_SCREEN_CALL'
        EXPORTING
          im_o_model = l_zzenhm_model
          im_trtyp   = ls_zzenhm_doc_info-trtyp.
  ENDCASE.
ENDENHANCEMENT.

When this step had been done, the custom header screen can be generated when the Custom Header button is clicked.

Add a Custom Screen on Purchase Requisition Header By Replacing Standard GUI Status

2.8 Step 8 – Add an implicit enhancement into method if_purchase_requisition~get_transaction_state

The method is a component of local class LCL_REQ_HEADER in function group MEREQ, and located at INCLUDE program LMEREQF12.

Based on the exporting parameter of the method, we know that this method is used for returning the transaction states of the purchase requisition, for example, whether the purchase requisition has been changed.

Add a Custom Screen on Purchase Requisition Header By Replacing Standard GUI Status

Why do we need to add this enhancement?

When users just change the data in the enhanced custom header screen but leave the standard data unchanged (EBAN, EBKN, TEXT, etc), the application will not recognize the changing of the document. So application will not trigger the saving process for the document.

In this case we need to overwrite the changed indicator of LCL_REQ_HEADER, so that the program can recognize and accept the changing of the document.

Because it has a CHECK statement in the method, we need to add the implicit enhancement at the beginning of the method; otherwise the implemented codes will be skipped under certain circumstance (for example, Create Mode, ME51N), see below screenshot.

Add a Custom Screen on Purchase Requisition Header By Replacing Standard GUI Status

So the enhancement is below:
ENHANCEMENT 1  ZME51N_TEST4.    "active version
if  sy-uname = 'CHENGANGRONG' AND
      SY-DYNNR = '0014' AND
      ( SY-TCODE = 'ME51N' OR
      SY-TCODE = 'ME52N' OR
      SY-TCODE = 'ME53N' OR
      SY-TCODE = 'ME54N' ).
IF my_state->changed IS INITIAL.
CALL FUNCTION 'ZPR_CHECK_TRANSACTION_STATE'
  EXPORTING
    im_banfn         = my_state->header-banfn
 CHANGING
   CH_CHANGED       = my_state->changed.
ENDIF.
endif.
ENDENHANCEMENT.

2.9 Step 9 – Implement the Badi ME_PROCESS_REQ_CUST, and then insert below codes into the method OPEN (It is easy to understand that application need to initialize and read the custom header data when a new purchase requisition is opened).

In my case, the Badi implementation is ZME_PROCESS_REQ_CUST .

Add a Custom Screen on Purchase Requisition Header By Replacing Standard GUI Status

METHOD if_ex_me_process_req_cust~open.
  IF sy-uname = 'CHENGANGRONG' AND
     ( sy-tcode = 'ME51N' OR
       sy-tcode = 'ME52N' OR
       sy-tcode = 'ME53N' OR
       sy-tcode = 'ME54N' ).
    CALL FUNCTION 'ZPR_OPEN'
      EXPORTING
        io_header = im_header.
  ENDIF.
ENDMETHOD.

2.10 Step 10 – Saving custom header data for purchase requisition.

I use the EXIT function module EXIT_SAPLMEREQ_008 as saving position of the custom header data (The SMOD enhancement is MEREQ001, it is a common enhancement, so that I would not explain the CMOD project in detail).

Maybe someone will ask me why do not put the saving process at method POST of Badi ME_PROCESS_REQ_CUST.

Actually I had tried but it doesn’t work in some case. For example, if user just changes the custom header data but leave the standard data unchanged (EBAN, EBKN, TEXT, etc), the application would not trigger the implemented POST method of ME_PROCESS_REQ_CUST. So I have to make the enhancement position at EXIT_SAPLMEREQ_008.

Add a Custom Screen on Purchase Requisition Header By Replacing Standard GUI Status

IF sy-uname = 'CHENGANGRONG' AND
   sy-dynnr = '0014' AND
   ( sy-tcode = 'ME51N' OR
     sy-tcode = 'ME52N' OR
     sy-tcode = 'ME53N' OR
     sy-tcode = 'ME54N' ).
    CALL FUNCTION 'ZPR_HEADER_CUSTOM_SAVE'
      EXPORTING
        im_banfn = im_banfn_new.
ENDIF.

2.11 Step 11 – Add a new public method zzcustom_after_post into local class LCL_REQ_HEADER.

Once we implement the custom header screen on purchase requisition, the system behaviors of change mode (ME52N) will have some difference from the original behaviors after saving the PR document.
The original behavior: the system will alternate the transaction type from change mode to display mode (my_state->trtyp). And changed indicator my_state->changed will be reset to SPACE. (see at the last of method prepare_post of local class lcl_req_header in INCLUDE program LMEREQF07)

Add a Custom Screen on Purchase Requisition Header By Replacing Standard GUI Status

New behavior of our implementation: If user only changes custom header data but leave standard data unchanged (EBAN, EBKN, TEXT, etc), the method prepare_post will raise an exception no_changes before reset of the changed indicator and alternation of transaction type. In this case the purchase requisition will leave to changed state and change mode after saving the PR document. This is different from the original system behavior.

Add a Custom Screen on Purchase Requisition Header By Replacing Standard GUI Status

To overcome the gap between original behavior and new behavior, we need to have a method to set the transaction type and changed indicator as what it is in standard behavior after the document is saved. So I introduce the new method zzcustom_after_post for local class LCL_REQ_HEADER.

In the definition part of LCL_REQ_HEADER (INCLUDE program LMEREQF07 of function group MEREQ), I make such implicit enhancement:

Add a Custom Screen on Purchase Requisition Header By Replacing Standard GUI Status

ENHANCEMENT 2  ZME51N_TEST4.    "active version
METHODS: zzcustom_after_post
                                   .
ENDENHANCEMENT.

And in the implementation part of LCL_REQ_HEADER (INCLUDE program LMEREQF08 of function group MEREQ), I make such implicit enhancement:

Add a Custom Screen on Purchase Requisition Header By Replacing Standard GUI Status

ENHANCEMENT 3  ZME51N_TEST4.    "active version
METHOD zzcustom_after_post.
    me->my_state->trtyp = me->my_state->aktyp = anz.

    me->my_state->changed = mmpur_no.
ENDMETHOD.                    "zzcustom_after_post
ENDENHANCEMENT.

And please see Step 12 on how we using the new enhancement method.

2.12 Step 12 – Add an implicit enhancement at the POST method of local class LCL_INSTANCE_FACTORY.

The POST method of local class LCL_INSTANCE_FACTORY is located at INCLUDE program LMEREQF06 of function group MEREQ.

Just as I had mentioned at above some steps, if user only change the custom header data but leave standard data unchanged (EBAN, EBKN, TEXT, etc), the application will not recognize the changing of the document.

Although we had added an implicit enhancement at Step 8 for replacing the changed indicator of the document, the application still doesn’t trigger the commit work, if no any standard data is changed.

If you have noticed that the custom function module ZPR_HEADER_CUSTOM_SAVE, which we place at EXIT function EXIT_SAPLMEREQ_008, is just a normal function module. But inside the function module there have another FM ZPR_HEADER_CUSTOM_SAVE_CORE is invoked by update task:

Add a Custom Screen on Purchase Requisition Header By Replacing Standard GUI Status

So we have to take a solution for triggering the commit work in case of standard data unchanged.

At last, by debugging, I found the best implementation position is at the end of POST method of LCL_INSTANCE_FACTORY.

Add a Custom Screen on Purchase Requisition Header By Replacing Standard GUI Status

ENHANCEMENT 4  ZME51N_TEST4.    "active version
  DATA: l_zzehm_banfn TYPE banfn.
  DATA: ls_zzehm_hashed_entry TYPE hash_table_entry.
  data: l_zzhm_original_changed type flag.
  IF   sy-uname = 'CHENGANGRONG' AND
        sy-dynnr = '0014' AND
        ( sy-tcode = 'ME51N' OR
        sy-tcode = 'ME52N' OR
        sy-tcode = 'ME53N' OR
        sy-tcode = 'ME54N' ).
    CALL FUNCTION 'ZPR_EXPORT_BUFFER'
      IMPORTING
        ex_banfn            = l_zzehm_banfn
        ex_original_changed = l_zzhm_original_changed.
    IF l_zzhm_original_changed IS INITIAL.
*  no changed for PR data(standard DB data)
*  program would not execute commit at previous step
*  in this case, we have to execute commit so that
*  the FM ZPR_HEADER_CUSTOM_SAVE_CORE can be submit to commit
*  (see FM EXIT_SAPLMEREQ_008 and ZPR_HEADER_CUSTOM_SAVE)
      IF im_no_commit EQ mmpur_no
         AND im_wait EQ cl_mmpur_constants=>no .
        COMMIT WORK.
      ELSEIF im_no_commit EQ mmpur_no
         AND im_wait EQ cl_mmpur_constants=>yes .
        COMMIT WORK AND WAIT.
      ENDIF.
    ENDIF.
    READ TABLE my_hash_table INTO ls_zzehm_hashed_entry
         WITH KEY banf = l_zzehm_banfn.
    IF sy-subrc = 0.
*  resume the changed indicator for header state
      ls_zzehm_hashed_entry-header->zzcustom_after_post( ).
    ENDIF.
  ENDIF.
ENDENHANCEMENT.

And now you will see the method zzcustom_after_post is called after the commit, so that the changed indicator and transaction type are reset.

1 comment: