Developer ToolsFree generatorPDF, Excel, Word exportSAP ECC 6.0All SAP ECC 6.0 tools

SAP BAdI Example Code Generator for ECC (PO, MIGO and Order Save Checks)

This generator produces method code for three classic BAdIs in SAP ECC 6.0 that block saving a purchase order, a goods movement in MIGO or a maintenance order when a field is missing for a plant or order type. The signatures match the standard interfaces, so the code pastes into the class SE19 generates.

Fill in

Classic BAdI implementations start with Z or Y.

afnam requisitioner, bednr requirement tracking number, matkl material group.

sgtxt item text, charg batch, lgort storage location.

ilart maintenance activity type, ktext short text.

Generated code
Download:

SE19 steps (all three BAdIs)

* 1. SE18: display the BAdI definition, check the interface methods
*    and whether it is multiple use or filter dependent.
* 2. SE19: Create implementation, Classic BAdI, enter the definition
*    name, then the implementation name, for example ZMM_CHECK_PO.
* 3. Double-click the method on the Interface tab; the class
*    ZCL_IM_ plus your implementation name is proposed. Paste the code.
* 4. Create message 001 in class ZMM in SE91, for example
*    'Field required for plant &1'.
* 5. Activate the class and the implementation, add both to one
*    transport request, and test in the development client.

ME_PROCESS_PO_CUST, method CHECK (ME21N / ME22N)

METHOD if_ex_me_process_po_cust~check.
* IM_HEADER TYPE REF TO IF_PURCHASE_ORDER_MM, IM_HOLD, IM_PARK,
* CHANGING CH_FAILED TYPE MMPUR_BOOL
  INCLUDE mm_messages_mac.

  DATA: lt_items TYPE purchase_order_items,
        ls_items TYPE purchase_order_item,
        ls_item  TYPE mepoitem.

  lt_items = im_header->get_items( ).
  LOOP AT lt_items INTO ls_items.
    ls_item = ls_items-item->get_data( ).
    IF ls_item-loekz IS INITIAL
       AND ls_item-werks = '1000'
       AND ls_item-afnam IS INITIAL.
      mmpur_message_forced 'E' 'ZMM' '001' ls_item-werks '' '' ''.
      ch_failed = 'X'.
    ENDIF.
  ENDLOOP.
ENDMETHOD.

MB_MIGO_BADI, methods LINE_MODIFY, LINE_DELETE, RESET, CHECK_ITEM (MIGO)

* CHECK_ITEM only receives I_LINE_ID, so buffer the item in LINE_MODIFY.
* In SE11 create table type ZMM_T_GOITEM with line type GOITEM, then add
* private instance attribute MT_GOITEM TYPE ZMM_T_GOITEM to the class.

METHOD if_ex_mb_migo_badi~line_modify.
  DATA ls_goitem TYPE goitem.
  ls_goitem = cs_goitem.
  ls_goitem-global_counter = i_line_id.
  DELETE mt_goitem WHERE global_counter = i_line_id.
  APPEND ls_goitem TO mt_goitem.
ENDMETHOD.

METHOD if_ex_mb_migo_badi~line_delete.
  DELETE mt_goitem WHERE global_counter = i_line_id.
ENDMETHOD.

METHOD if_ex_mb_migo_badi~reset.
  CLEAR mt_goitem.
ENDMETHOD.

METHOD if_ex_mb_migo_badi~check_item.
* CHANGING ET_BAPIRET2 TYPE BAPIRET2_T
  DATA: ls_goitem TYPE goitem,
        ls_ret    TYPE bapiret2.

  READ TABLE mt_goitem INTO ls_goitem
       WITH KEY global_counter = i_line_id.
  IF sy-subrc = 0
     AND ls_goitem-werks = '1000'
     AND ls_goitem-sgtxt IS INITIAL.
    ls_ret-type       = 'E'.
    ls_ret-id         = 'ZMM'.
    ls_ret-number     = '001'.
    ls_ret-message_v1 = ls_goitem-werks.
    APPEND ls_ret TO et_bapiret2.
  ENDIF.
ENDMETHOD.

WORKORDER_UPDATE, method AT_SAVE (IW31 / IW32, CO01 / CO02)

METHOD if_ex_workorder_update~at_save.
* IMPORTING IS_HEADER_DIALOG TYPE COBAI_S_HEADER_DIALOG
* EXCEPTIONS ERROR_WITH_MESSAGE
  IF is_header_dialog-auart = 'PM01'
     AND is_header_dialog-ilart IS INITIAL.
    MESSAGE e001(ZMM) WITH is_header_dialog-aufnr
            RAISING error_with_message.
  ENDIF.
ENDMETHOD.

Signatures were taken from the interfaces IF_EX_ME_PROCESS_PO_CUST, IF_EX_MB_MIGO_BADI and IF_EX_WORKORDER_UPDATE; confirm them in SE18 on your release. Confirm in SE11 that COBAI_S_HEADER_DIALOG contains the order header fields you test (AUFNR, AUART, ILART, KTEXT). WORKORDER_UPDATE also fires for production orders, so keep the order type condition. Check in SE19 whether an active implementation of MB_MIGO_BADI already exists before creating another.

Want your enhancement checked before transport?

Send us the generated method and your release level and we will review the signature, message handling and side effects on background postings.

Optional. The tool and every export work without this. No spam.

Was this tool useful?

How to use it

Enter the implementation name prefix, the plant, the field each check should require, the order type for the order check and your message class and number. The tool writes one block per BAdI plus the SE19 steps. Create the message in SE91 first, with a placeholder such as &1 for the plant or order number, so the user sees a clear text. Paste each method into the class of its own implementation; you do not need all three. The checks are mandatory-field rules; to turn one into a value limit, replace the IS INITIAL test with a comparison such as ls_item-netpr > 10000, and to make it a plant restriction, test WERKS alone.

Why each BAdI is coded differently

ME_PROCESS_PO_CUST gives CHECK an object reference IM_HEADER of type IF_PURCHASE_ORDER_MM. You get the items with GET_ITEMS, and each item object returns its MEPOITEM data through GET_DATA. Errors go into the PO message log with the MMPUR_MESSAGE_FORCED macro from include MM_MESSAGES_MAC, and setting CH_FAILED stops the save. MB_MIGO_BADI is different: CHECK_ITEM only passes I_LINE_ID and a BAPIRET2 table, so the item data must be buffered in LINE_MODIFY, which receives CS_GOITEM, and cleaned up in LINE_DELETE and RESET. WORKORDER_UPDATE~AT_SAVE passes the header as IS_HEADER_DIALOG and declares the exception ERROR_WITH_MESSAGE, so a MESSAGE with RAISING both shows the text and cancels the save.

Worked example

A plant manager wants every PO for plant 1000 to name a requisitioner, every goods receipt in that plant to carry an item text, and every PM01 order to have a maintenance activity type. With plant 1000, PO field afnam, MIGO field sgtxt, order type PM01, order field ilart and message ZMM 001 'Field required for plant &1', the three blocks give exactly those checks. Test ME21N with and without the requisitioner, MIGO with a blank item text, and IW31 without an activity type. Each should stop with your message; with the field filled, each should save normally.

Common mistakes

Do not use MESSAGE type E directly inside ME_PROCESS_PO_CUST; it can break the Enjoy transaction flow, which is why the macro and CH_FAILED exist. Do not read the MIGO screen through field symbols to other programs; the LINE_MODIFY buffer is the supported route. Remember that classic BAdI implementations are inactive until you activate the implementation itself, not just the class. Avoid database updates in these methods: they are check points, and a COMMIT WORK inside them can corrupt the document's update task. Finally, test background postings: BAPIs such as BAPI_PO_CREATE1 also run ME_PROCESS_PO_CUST, so your check applies to interfaces too.

Frequently Asked Questions

How do I implement a classic BAdI in SAP ECC?

Find the BAdI in SE18 and check its interface. In SE19 create a classic implementation with a Z name, enter the definition, and SAP proposes a class named ZCL_IM_ plus the implementation name. Code the methods you need, activate the class, then activate the implementation and record both in a transport.

Can you give an example of a BAdI in SAP ABAP?

A common example is ME_PROCESS_PO_CUST method CHECK: loop over IM_HEADER->GET_ITEMS( ), read each item with GET_DATA( ) into MEPOITEM, and if a required field is empty for a plant, raise a message with MMPUR_MESSAGE_FORCED and set CH_FAILED to X. The PO then cannot be saved until the field is filled.

How do I raise an error in MB_MIGO_BADI CHECK_ITEM?

Append a BAPIRET2 line with TYPE E, your message class in ID, the number in NUMBER and variables in MESSAGE_V1 to MESSAGE_V4 to ET_BAPIRET2. Because CHECK_ITEM only receives the line ID, read the item from a buffer you fill in LINE_MODIFY from CS_GOITEM.

What is the difference between a classic BAdI and a new kernel BAdI?

Classic BAdIs, like the three here, are defined in SE18 and implemented in SE19 with a generated class, and are called through CL_EXITHANDLER. Kernel BAdIs are part of enhancement spots, called with GET BADI and CALL BADI, and implemented in enhancement implementations. Many ECC areas still use classic BAdIs, so check the definition type in SE18.

If you want developers to find which BAdIs, user exits and Z checks already touch a transaction by asking your ECC system in plain English, we can set up a private, read-only AI layer over your repository.

ArchRay builder
Design the on-prem AI stack for SAP ECC 6.0: model, GPUs, RAG pipeline, guardrails
See memory, speed and cost as you swap parts, then export the diagram. Free, in your browser.
Open the builder

Keep exploring