# Custom Inbound IDoc Function Module in SAP ABAP: Skeleton Generator

> Source: https://netray.co/tools/sap-ecc-inbound-idoc-function-module-skeleton-generator
> Publisher: Netray (netray.co), AI and integration engineering for ERP and manufacturing systems.
> Section: Free Tools

## Short answer

Generate a ready-to-adapt inbound IDoc function module for a custom message type and segment: standard interface, segment cast, validation, status 51 or 53, workflow return variables and the configuration steps.

## Category

developer

## Erp

SAP ECC 6.0

## Audience

- ABAP developer
- SAP integration consultant

## Tool

**Kind:** template

**Output:** code

**Language:** abap

**Fields:**

#### Function module name

**Key:** fm_name

**Type:** text

**Default:** Z_IDOC_INPUT_ZMATSTAT

#### Message type

**Key:** mestyp

**Type:** text

**Default:** ZMATSTAT

#### Basic type

**Key:** idoctp

**Type:** text

**Default:** ZMATSTAT01

#### Segment type

**Key:** segment

**Type:** text

**Default:** Z1MATSTAT

#### Value field in segment and table

**Key:** valfield

**Type:** text

**Default:** STATUS

**Help:** The segment must also contain MATNR and WERKS

#### Target Z table

**Key:** ztable

**Type:** text

**Default:** ZMAT_STATUS

#### Process code

**Key:** procode

**Type:** text

**Default:** ZMST

**Blocks:**

#### Function module (create in SE37, interface as in the header comment)

**Body:** FUNCTION {{fm_name}}.
*----------------------------------------------------------------------
* Local interface (define these in SE37, same as IDOC_INPUT_ORDERS):
*  IMPORTING
*     VALUE(INPUT_METHOD)          LIKE  BDWFAP_PAR-INPUTMETHD
*     VALUE(MASS_PROCESSING)       LIKE  BDWFAP_PAR-MASS_PROC
*  EXPORTING
*     VALUE(WORKFLOW_RESULT)       LIKE  BDWF_PARAM-RESULT
*     VALUE(APPLICATION_VARIABLE)  LIKE  BDWF_PARAM-APPL_VAR
*     VALUE(IN_UPDATE_TASK)        LIKE  BDWFAP_PAR-UPDATETASK
*     VALUE(CALL_TRANSACTION_DONE) LIKE  BDWFAP_PAR-CALLTRANS
*  TABLES
*      IDOC_CONTRL STRUCTURE  EDIDC
*      IDOC_DATA STRUCTURE  EDIDD
*      IDOC_STATUS STRUCTURE  BDIDOCSTAT
*      RETURN_VARIABLES STRUCTURE  BDWFRETVAR
*      SERIALIZATION_INFO STRUCTURE  BDI_SER
*  EXCEPTIONS
*      WRONG_FUNCTION_CALLED
*----------------------------------------------------------------------

  DATA: ls_ctrl  TYPE edidc,
        ls_data  TYPE edidd,
        ls_seg   TYPE {{segment}},
        ls_row   TYPE {{ztable}},
        lt_rows  TYPE STANDARD TABLE OF {{ztable}},
        ls_stat  TYPE bdidocstat,
        ls_ret   TYPE bdwfretvar,
        lv_error TYPE c,
        lv_any_error TYPE c.

  in_update_task        = space.
  call_transaction_done = space.
  application_variable  = space.

  LOOP AT idoc_contrl INTO ls_ctrl.

    IF ls_ctrl-mestyp <> '{{mestyp}}'.
      RAISE wrong_function_called.
    ENDIF.

    CLEAR: lv_error, lt_rows.

    LOOP AT idoc_data INTO ls_data
         WHERE docnum = ls_ctrl-docnum
           AND segnam = '{{segment}}'.

      ls_seg = ls_data-sdata.
      CLEAR ls_row.

      CALL FUNCTION 'CONVERSION_EXIT_MATN1_INPUT'
        EXPORTING
          input        = ls_seg-matnr
        IMPORTING
          output       = ls_row-matnr
        EXCEPTIONS
          length_error = 1
          OTHERS       = 2.
      ls_row-werks      = ls_seg-werks.
      ls_row-{{valfield}} = ls_seg-{{valfield}}.

*     Validation: material must exist in the plant
      SELECT SINGLE werks FROM marc INTO ls_row-werks
        WHERE matnr = ls_row-matnr
          AND werks = ls_row-werks.
      IF sy-subrc <> 0.
        lv_error = 'X'.
        CLEAR ls_stat.
        ls_stat-docnum = ls_ctrl-docnum.
        ls_stat-status = '51'.
        ls_stat-msgty  = 'E'.
        ls_stat-msgid  = '00'.
        ls_stat-msgno  = '398'.
        ls_stat-msgv1  = 'Material not in plant:'.
        ls_stat-msgv2  = ls_seg-matnr.
        ls_stat-msgv3  = ls_seg-werks.
        ls_stat-segnum = ls_data-segnum.
        APPEND ls_stat TO idoc_status.
        EXIT.
      ENDIF.

      APPEND ls_row TO lt_rows.
    ENDLOOP.

    CLEAR ls_ret.
    ls_ret-doc_number = ls_ctrl-docnum.

    IF lv_error IS INITIAL.
*     Application update. ALE commits after the function module returns.
      MODIFY {{ztable}} FROM TABLE lt_rows.

*     BAPI alternative instead of the Z table:
*     CALL FUNCTION 'Z_YOUR_BAPI' ... TABLES return = lt_return.
*     Map BAPIRET2 lines of type E or A to status 51 lines.

      CLEAR ls_stat.
      ls_stat-docnum = ls_ctrl-docnum.
      ls_stat-status = '53'.
      ls_stat-msgty  = 'S'.
      ls_stat-msgid  = '00'.
      ls_stat-msgno  = '398'.
      ls_stat-msgv1  = 'Material status updated'.
      APPEND ls_stat TO idoc_status.
      ls_ret-wf_param = 'Processed_IDOCs'.
    ELSE.
      lv_any_error = 'X'.
      ls_ret-wf_param = 'Error_IDOCs'.
    ENDIF.
    APPEND ls_ret TO return_variables.

  ENDLOOP.

  IF lv_any_error IS INITIAL.
    workflow_result = '0'.
  ELSE.
    workflow_result = '99999'.
  ENDIF.

ENDFUNCTION.

#### Configuration steps

**Body:** * WE31  Create segment type {{segment}} with fields MATNR, WERKS, {{valfield}} and release it
* WE30  Create basic type {{idoctp}} containing {{segment}} and release it
* WE81  Create message type {{mestyp}}
* WE82  Link message type {{mestyp}} to basic type {{idoctp}}
* SE11  Create table {{ztable}} with MANDT, MATNR, WERKS (keys) and {{valfield}}
* SE37  Create {{fm_name}} with the interface above
* WE57  Assign {{fm_name}} to {{mestyp}} / {{idoctp}}, function type F, direction 2
* BD51  Register {{fm_name}} with input type 0 (mass) or 1 (individual)
* WE42  Create inbound process code {{procode}} pointing to {{fm_name}}
* WE20  Add {{mestyp}} with process code {{procode}} to the sending partner (inbound parameters)
* WE19  Test: copy or build an IDoc and start inbound processing with {{fm_name}}
* BD87  Reprocess IDocs in status 51 after fixing data

**Notes:** The interface must match the standard inbound interface exactly, otherwise ALE raises a runtime error; compare with IDOC_INPUT_ORDERS in SE37. Message 00 398 is the generic four-placeholder message; replace it with your own message class for production. The segment structure must contain MATNR and WERKS with those names, or adapt the mapping lines. Do not COMMIT WORK inside the function module unless input type 1 is used and you know why.

## Content

**Intro:** This generator produces an inbound IDoc function module for SAP ECC 6.0 for a custom message type and segment, with the standard ALE interface, segment cast from SDATA, validation, status 51 and 53 records and workflow return variables. It also lists the WE31 to WE20 configuration steps that connect the function module to the partner profile.

**Sections:**

#### How inbound IDoc processing reaches your code

**Body:** When an IDoc arrives, ALE reads the partner profile (WE20) for the sender and message type, finds the process code (WE42) and calls the function module behind it. The function module receives the control records in IDOC_CONTRL and all segments in IDOC_DATA, one EDIDD line per segment. It must write at least one status line per IDoc into IDOC_STATUS: 53 for posted, 51 for application error. RETURN_VARIABLES tells workflow which IDocs succeeded (Processed_IDOCs) or failed (Error_IDOCs), and WORKFLOW_RESULT 99999 triggers error handling.

**Bullets:**

- WE57 links the function module to message and basic type.
- BD51 defines input type: 0 mass, 1 individual, 2 individual with IDoc lock in CALL TRANSACTION.
- Status 51 IDocs are reprocessed with BD87 after the cause is fixed.

#### How to use it

**Body:** Enter the function module, message type, basic type, segment, target table and process code. The code assumes the segment has MATNR, WERKS and one value field, and writes them into a custom table. Create the objects in the order of the configuration block, paste the body into SE37 after defining the interface, then test with WE19. For a BAPI target, replace the MODIFY statement with the BAPI call and convert BAPIRET2 errors into status 51 lines.

#### Worked example

**Body:** Message type ZMATSTAT with segment Z1MATSTAT carries MATNR 100-200, WERKS 1000, STATUS QA. The function module converts the material number with CONVERSION_EXIT_MATN1_INPUT, checks MARC for material 100-200 in plant 1000 and, if found, writes the row to ZMAT_STATUS and sets status 53. If the material is not extended to the plant, the IDoc gets status 51 with the text Material not in plant: 100-200 1000, visible in WE02 and BD87.

#### Gotchas

**Body:** Rows are collected per IDoc and written only when the whole IDoc is valid, so a failed IDoc never leaves half its data behind. Do not issue MESSAGE statements of type E inside the function module: they abort the whole packet in mass processing. Keep the interface identical to the standard one, including the WRONG_FUNCTION_CALLED exception. If the IDoc must update standard objects, call a BAPI rather than writing SAP tables, and if that BAPI needs a commit, check how input type and ALE commit handling interact.

**Cta:** If you want integration support staff to ask about failed inbound IDocs and their causes in plain English on your own servers, we can set that up over your ECC system.

**Faq:**

#### How do I create an inbound IDoc function module in SAP?

**Answer:** Copy the interface of a standard inbound function module such as IDOC_INPUT_ORDERS in SE37, then loop over IDOC_CONTRL and IDOC_DATA, cast SDATA to your segment structure, process the data and append status lines. Register it in WE57 and BD51, create a process code in WE42 and add it to the partner profile in WE20.

#### How do I set the IDoc status to 51 or 53 in the function module?

**Answer:** Append a line to IDOC_STATUS with DOCNUM, STATUS 51 or 53 and the message fields MSGTY, MSGID, MSGNO and MSGV1 to MSGV4. ALE writes these into EDIDS after the function module returns. Also fill RETURN_VARIABLES with Processed_IDOCs or Error_IDOCs for that DOCNUM.

#### How do I read a custom segment in an inbound IDoc?

**Answer:** Loop at IDOC_DATA where SEGNAM equals the segment type and move SDATA into a variable typed with the segment structure created in WE31. All segment fields are character-like, so the move maps the 1000-character SDATA onto the fields by position.

#### How do I test a custom inbound IDoc without a partner system?

**Answer:** Use WE19. Start from an existing IDoc or from the basic type, edit the segment values, then choose inbound function module and enter your function module, or standard inbound to go through the partner profile. The test IDoc gets its own number and status records.

## Search terms

inbound idoc creation example in sap abap, custom inbound idoc function module, idoc in sap abap, sap idoc custom segments, how to process idoc in sap, we57 bd51 we42, sap idoc bapi integration

---
Talk to an engineer: https://netray.co/contact?intent=erp_ai | Machine catalog: https://netray.co/agent/catalog.json
