IDoc Part 6: Inbound Process Code and Custom Function Module
Build a custom inbound IDoc: own message type and basic type, the standard inbound function module interface (IDOC CONTRL, IDOC DATA, IDOC STATUS, RETURN VARIABLES, WORKFLOW RESULT), process code in WE42, assignment in WE57/BD51, and correct status handling.
Explanation
📌 KEY POINTS
✅ A custom inbound FM uses SAP's fixed interface: IDOC_CONTRL, IDOC_DATA (in), IDOC_STATUS, RETURN_VARIABLES, WORKFLOW_RESULT (out), INPUT_METHOD, MASS_PROCESSING.
✅ For each IDoc, the FM appends one status record (53 or 51) and a RETURN_VARIABLES entry ("Processed_IDOCs" or "Error_IDOCs").
✅ Registration: WE57 (FM ↔ basic type/message type), BD51 (input type, e.g. 0 mass or 1 single), WE42 (process code → FM), WE20 (partner profile uses the process code).
⚠️ The FM must never COMMIT WORK itself (the IDoc framework commits) and must never stop with MESSAGE E — errors go into IDOC_STATUS.
━━━━━━━━━━━━━━━━━━━━
▶ WHERE WE ARE
Part 3 used SAP's inbound FMs. When a partner sends data SAP has no standard IDoc for, you build your own.
━━━━━━━━━━━━━━━━━━━━
▶ 1. OBJECTS TO CREATE
- Segment(s) WE31 (e.g. Z1PROJHDR), basic type WE30 (ZPROJECT01), message type WE81 (ZPROJECT), assignment WE82.
- Function module Z_IDOC_INPUT_ZPROJECT with the standard interface (copy from IDOC_INPUT_ORDERS signature).
- WE57: assign FM to basic type and message type (direction 2 inbound, type F function module).
- BD51: register FM with input type (0 = mass processing allowed, 1 = single IDoc, dialog possible).
- WE42: process code ZPRJ → FM.
- WE20: partner profile inbound parameter ZPROJECT → ZPRJ.
━━━━━━━━━━━━━━━━━━━━
▶ 2. FM LOGIC PER IDOC
- Loop at IDOC_CONTRL (one per IDoc when mass processing).
- Read that IDoc's segments from IDOC_DATA (WHERE docnum = …); move SDATA into typed segment structures.
- Validate and post (BAPI/application FM) — without COMMIT.
- Append status: 53 with document reference, or 51 with message ID/number/variables.
- Fill RETURN_VARIABLES: WF_PARAM 'Processed_IDOCs' (success) or 'Error_IDOCs' with DOC_NUMBER.
- WORKFLOW_RESULT = '99999' on error (triggers error workflow), '0' on success.
━━━━━━━━━━━━━━━━━━━━
▶ 3. ROLLBACK HANDLING
If a posting fails after partial updates, call BAPI_TRANSACTION_ROLLBACK (or ROLLBACK WORK) carefully: in mass processing it affects all IDocs of the package — safer to use input type 1 (single) for postings that can partially fail, or package size 1.
━━━━━━━━━━━━━━━━━━━━
▶ 4. TESTING
WE19 with "inbound function module" option allows debugging the FM directly with a copied IDoc.
━━━━━━━━━━━━━━━━━━━━
▶ STEP BY STEP
- Create segment, basic type and message type in a sandbox.
- Create the FM (code example) and register it in WE57, BD51, WE42.
- Test with WE19 and check status records in WE02.
✅ CHECKPOINT: you can build a custom inbound IDoc function module with correct status handling.
Code example
FUNCTION z_idoc_input_zproject.*"----------------------------------------------------------------------*" 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*"---------------------------------------------------------------------- DATA: ls_hdr TYPE z1projhdr, lv_error TYPE abap_bool. LOOP AT idoc_contrl. CLEAR: ls_hdr, lv_error. * ===== Step 1: read segments of THIS IDoc ===== LOOP AT idoc_data WHERE docnum = idoc_contrl-docnum. CASE idoc_data-segnam. WHEN 'Z1PROJHDR'. ls_hdr = idoc_data-sdata. ENDCASE. ENDLOOP. * ===== Step 2: validate ===== IF ls_hdr-projid IS INITIAL. lv_error = abap_true. idoc_status-msgid = 'ZIDOC'. idoc_status-msgno = '001'. " 'Project ID missing' ELSE.* ===== Step 3: post (no COMMIT here - framework commits) ===== CALL FUNCTION 'Z_PROJECT_SAVE' IN UPDATE TASK EXPORTING is_project = ls_hdr. idoc_status-msgid = 'ZIDOC'. idoc_status-msgno = '002'. " 'Project & saved' idoc_status-msgv1 = ls_hdr-projid. ENDIF. * ===== Step 4: status record + return variables ===== idoc_status-docnum = idoc_contrl-docnum. idoc_status-repid = sy-repid. IF lv_error = abap_true. idoc_status-status = '51'. idoc_status-msgty = 'E'. return_variables-wf_param = 'Error_IDOCs'. workflow_result = '99999'. ELSE. idoc_status-status = '53'. idoc_status-msgty = 'S'. return_variables-wf_param = 'Processed_IDOCs'. ENDIF. APPEND idoc_status. return_variables-doc_number = idoc_contrl-docnum. APPEND return_variables. CLEAR idoc_status. ENDLOOP. in_update_task = 'X'. " own updates registered in update taskENDFUNCTION. * Registration: WE57 (FM <-> ZPROJECT01/ZPROJECT, direction 2), BD51 (input type 1),* WE42 (process code ZPRJ), WE20 (partner inbound ZPROJECT -> ZPRJ)Real project scenario
A warehouse partner sent project assignments that SAP had no standard IDoc for. The first custom FM called COMMIT WORK and MESSAGE E on errors: failing IDocs ended with dumps, and successful ones were sometimes committed together with half-processed data.
The rewrite followed the standard interface: status records per IDoc, no commit, updates in update task, single-IDoc input type. Errors now appear as clean status 51 records with message texts in BD87.
Common mistakes
- COMMIT WORK or MESSAGE E inside the inbound FM.
- Reading segments of all IDocs instead of WHERE docnum = current.
- Missing WE57/BD51 registration.
- No RETURN_VARIABLES entries.
- Rollback in mass processing affecting other IDocs.
Best practices
- Copy the interface of a standard inbound FM.
- One status record per IDoc (53/51) with message variables.
- Updates via update task/BAPI without commit.
- Input type 1 for partial-failure postings.
- Test with WE19 inbound FM debugging.
Interview angle
Questions: "How do you create a custom inbound IDoc?", "What is the interface of an inbound IDoc FM?", "Which settings link the FM?"
Strong answer: segments WE31, basic type WE30, message type WE81/WE82; FM with IDOC_CONTRL/IDOC_DATA/IDOC_STATUS/RETURN_VARIABLES/WORKFLOW_RESULT; loop per IDoc, read segments by DOCNUM, post without COMMIT, status 53/51, return variables; register WE57, BD51, WE42, WE20; test WE19.
Practice this lesson
Quick check
1. What must a custom inbound IDoc function module NOT do?
2. In an inbound partner profile, what is the primary purpose of assigning a process code to a message type?
3. By SAP convention, function modules that process inbound IDoc data for a given message type typically follow which naming pattern?
Interview questions
1. How do you find the function module used for inbound IDoc processing?
Answer it in your own words first, then compare.
2. A partner sends delivery data that no standard IDoc covers. How would you build and register a custom inbound IDoc?
Answer it in your own words first, then compare.
Reference-verified: the steps are checked against official SAP documentation and tutorials, and object and field names in the sample code are checked for consistency. The code has not been compiled or run on an SAP system by ERPClimb. Syntax marked release-dependent varies by SAP release, so check it in your own system.
More lessons in this topic
- IDoc Part 1: What an IDoc Is — Inbound, Outbound and the Big Picture
- IDoc Part 10: Debugging and Production Support
- IDoc Part 2: Message Type, Basic Type and Extension
- IDoc Part 3: Inbound IDoc Processing
- IDoc Part 4: Outbound IDocs, Distribution Model and Reprocessing
- IDoc Part 5: Partner Profile, Port and RFC Configuration
- IDoc Part 7: Outbound Triggering — Output Control and Change Pointers
- IDoc Part 8: Status Codes and Reprocessing with BD87