ABAP IDoc Processing: Intermediate Documents for EDI Communication

Category
ABAP-Statements
Published
Author
Johannes

IDocs (Intermediate Documents) are SAP’s standard format for electronic data interchange (EDI). They enable asynchronous communication between SAP systems and external partners.

IDoc Structure

ComponentDescription
Control RecordControl information (EDIDC)
Data RecordsPayload in segments (EDIDD)
Status RecordsProcessing status (EDIDS)

IDoc Types and Message Types

ElementTransactionDescription
IDoc TypeWE30Data structure
Message TypeWE81Business process
SegmentWE31Data container
PartnerWE20Communication partner

Basic Examples

Creating an IDoc Manually

DATA: lt_edidc TYPE TABLE OF edidc,
ls_edidc TYPE edidc,
lt_edidd TYPE TABLE OF edidd,
ls_edidd TYPE edidd.
" Fill control record
ls_edidc-mestyp = 'ORDERS'.
ls_edidc-idoctp = 'ORDERS05'.
ls_edidc-rcvprt = 'LS'.
ls_edidc-rcvprn = 'PARTNER01'.
ls_edidc-sndprt = 'LS'.
ls_edidc-sndprn = sy-sysid.
APPEND ls_edidc TO lt_edidc.
" Data Segment E1EDK01 - Header
ls_edidd-segnam = 'E1EDK01'.
ls_edidd-sdata = 'Order header data...'.
APPEND ls_edidd TO lt_edidd.
" Data Segment E1EDP01 - Item
ls_edidd-segnam = 'E1EDP01'.
ls_edidd-sdata = 'Item data...'.
APPEND ls_edidd TO lt_edidd.
" Create IDoc
CALL FUNCTION 'IDOC_INBOUND_ASYNCHRONOUS'
TABLES
idoc_control_rec_40 = lt_edidc
idoc_data_rec_40 = lt_edidd.

Filling IDoc with Structure

TYPES: BEGIN OF ty_e1edk01,
belnr TYPE char35,
datum TYPE char8,
waers TYPE char3,
END OF ty_e1edk01.
DATA: ls_e1edk01 TYPE ty_e1edk01,
ls_edidd TYPE edidd.
ls_e1edk01-belnr = '4500000123'.
ls_e1edk01-datum = '20250115'.
ls_e1edk01-waers = 'EUR'.
ls_edidd-segnam = 'E1EDK01'.
ls_edidd-sdata = ls_e1edk01. " Structure assignment
APPEND ls_edidd TO lt_edidd.

Reading and Analyzing IDoc

DATA: lv_docnum TYPE edi_docnum VALUE '0000000000012345',
ls_edidc TYPE edidc,
lt_edidd TYPE TABLE OF edidd,
lt_edids TYPE TABLE OF edids.
" Read control record
SELECT SINGLE * FROM edidc INTO ls_edidc
WHERE docnum = lv_docnum.
" Read data records
SELECT * FROM edid4 INTO TABLE lt_edidd
WHERE docnum = lv_docnum
ORDER BY segnum.
" Read status records
SELECT * FROM edids INTO TABLE lt_edids
WHERE docnum = lv_docnum
ORDER BY countr DESCENDING.
LOOP AT lt_edidd INTO DATA(ls_data).
WRITE: / ls_data-segnam, ls_data-sdata(50).
ENDLOOP.

IDoc Outbound via Master IDoc

DATA: ls_master_idoc TYPE edidc,
lt_comm_idocs TYPE TABLE OF edidc.
" Master IDoc parameters
ls_master_idoc-mestyp = 'MATMAS'.
ls_master_idoc-idoctp = 'MATMAS05'.
ls_master_idoc-rcvprt = 'LS'.
ls_master_idoc-rcvprn = 'CLNT800'.
" Trigger IDoc dispatch
CALL FUNCTION 'MASTER_IDOC_DISTRIBUTE'
EXPORTING
master_idoc_control = ls_master_idoc
TABLES
communication_idoc_control = lt_comm_idocs
master_idoc_data = lt_edidd
EXCEPTIONS
error_in_idoc_control = 1
error_writing_idoc_status = 2
error_in_idoc_data = 3
sending_logical_system_unknown = 4
OTHERS = 5.
IF sy-subrc = 0.
COMMIT WORK.
LOOP AT lt_comm_idocs INTO DATA(ls_comm).
WRITE: / 'IDoc created:', ls_comm-docnum.
ENDLOOP.
ENDIF.

Setting IDoc Status

DATA: lt_status TYPE TABLE OF bdidocstat,
ls_status TYPE bdidocstat.
ls_status-docnum = lv_docnum.
ls_status-status = '53'. " Application document posted
ls_status-msgty = 'S'.
ls_status-msgid = 'E0'.
ls_status-msgno = '000'.
ls_status-msgv1 = 'Successfully processed'.
APPEND ls_status TO lt_status.
CALL FUNCTION 'IDOC_STATUS_WRITE_TO_DATABASE'
EXPORTING
idoc_number = lv_docnum
TABLES
idoc_status = lt_status
EXCEPTIONS
idoc_foreign_lock = 1
idoc_not_found = 2
idoc_status_records_empty = 3
OTHERS = 4.
COMMIT WORK.

Inbound Function Module for Custom IDoc Type

FUNCTION z_idoc_inbound_orders.
*"----------------------------------------------------------------------
*" IMPORTING
*" VALUE(INPUT_METHOD) TYPE BDWFAP_PAR-INPUTMETHD
*" VALUE(MASS_PROCESSING) TYPE BDWFAP_PAR-MASS_PROC
*" EXPORTING
*" VALUE(WORKFLOW_RESULT) TYPE BDWFAP_PAR-RESULT
*" VALUE(APPLICATION_VARIABLE) TYPE BDWFAP_PAR-APPL_VAR
*" VALUE(IN_UPDATE_TASK) TYPE BDWFAP_PAR-UPDATETASK
*" VALUE(CALL_TRANSACTION_DONE) TYPE 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_order TYPE zorder_header,
ls_item TYPE zorder_item,
lt_items TYPE TABLE OF zorder_item.
LOOP AT idoc_contrl INTO DATA(ls_control).
" Process IDoc data
LOOP AT idoc_data INTO DATA(ls_data)
WHERE docnum = ls_control-docnum.
CASE ls_data-segnam.
WHEN 'Z1ORDER_HEADER'.
ls_order = ls_data-sdata.
WHEN 'Z1ORDER_ITEM'.
ls_item = ls_data-sdata.
APPEND ls_item TO lt_items.
ENDCASE.
ENDLOOP.
" Create order
TRY.
" Business logic here
" Success status
DATA(ls_status) = VALUE bdidocstat(
docnum = ls_control-docnum
status = '53'
msgty = 'S'
msgid = 'ZMM'
msgno = '001' ).
APPEND ls_status TO idoc_status.
CATCH cx_root INTO DATA(lx_error).
" Error status
ls_status = VALUE #(
docnum = ls_control-docnum
status = '51'
msgty = 'E'
msgid = 'ZMM'
msgno = '002'
msgv1 = lx_error->get_text( ) ).
APPEND ls_status TO idoc_status.
ENDTRY.
ENDLOOP.
ENDFUNCTION.

Configuring ALE Distribution

" Read distribution model
DATA: lt_receivers TYPE TABLE OF bdcp_receiver.
CALL FUNCTION 'ALE_MODEL_DETERMINE_RECEIVERS'
EXPORTING
message_type = 'MATMAS'
sending_logical_system = 'SRCCLNT100'
TABLES
receivers = lt_receivers
EXCEPTIONS
no_entry_in_model = 1
OTHERS = 2.
LOOP AT lt_receivers INTO DATA(ls_receiver).
WRITE: / 'Receiver:', ls_receiver-rcvprn.
ENDLOOP.

Selecting and Evaluating IDocs

SELECT edidc~docnum, edidc~status, edidc~credat, edidc~cretim,
edidc~mestyp, edidc~idoctp, edidc~rcvprn
FROM edidc
WHERE mestyp = 'ORDERS'
AND status IN ('51', '56') " Error status
AND credat >= @( sy-datum - 7 )
INTO TABLE @DATA(lt_error_idocs).
LOOP AT lt_error_idocs INTO DATA(ls_idoc).
WRITE: / ls_idoc-docnum, ls_idoc-status, ls_idoc-credat.
ENDLOOP.

Reprocessing IDoc

DATA: lt_docnum TYPE TABLE OF edi_docnum.
APPEND lv_docnum TO lt_docnum.
CALL FUNCTION 'EDI_DOCUMENT_OPEN_FOR_PROCESS'
EXPORTING
document_number = lv_docnum
EXCEPTIONS
document_foreign_lock = 1
document_not_exist = 2
document_not_open = 3
status_is_unable_proc = 4
OTHERS = 5.
IF sy-subrc = 0.
" Reprocess IDoc
CALL FUNCTION 'IDOC_INBOUND_SINGLE'
EXPORTING
pi_idoc_number = lv_docnum
EXCEPTIONS
parameter_error = 1
idoc_not_found = 2
lock_error = 3
OTHERS = 4.
CALL FUNCTION 'EDI_DOCUMENT_CLOSE_PROCESS'
EXPORTING
document_number = lv_docnum.
ENDIF.

Change Pointers for IDoc Creation

" Activate change pointers (BD52/BD61)
" BD50: Message Type <-> Object
" BD52: Change Pointer active
" Create change pointer manually
DATA: lt_cp TYPE TABLE OF bdcp2.
APPEND VALUE #(
mestyp = 'MATMAS'
objkey = 'MATNR'
tabkey = '000000000000100000'
chngid = 'U'
cdchgid = sy-datum
cdchgtm = sy-uzeit
) TO lt_cp.
CALL FUNCTION 'CHANGE_POINTERS_CREATE'
TABLES
change_pointers = lt_cp.
" Process change pointers (RBDMIDOC)
CALL FUNCTION 'RBDMIDOC'
EXPORTING
mestyp = 'MATMAS'.

Processing Segment Data with Structure

" Dynamic segment mapping
DATA: lo_struct TYPE REF TO cl_abap_structdescr.
LOOP AT lt_edidd INTO DATA(ls_segment).
" Determine structure for segment
DATA(lv_segdef) = 'E1' && ls_segment-segnam+2.
TRY.
lo_struct ?= cl_abap_typedescr=>describe_by_name( lv_segdef ).
DATA: lr_data TYPE REF TO data.
CREATE DATA lr_data TYPE HANDLE lo_struct.
ASSIGN lr_data->* TO FIELD-SYMBOL(<fs_segment>).
" Transfer data
<fs_segment> = ls_segment-sdata.
" Process fields
LOOP AT lo_struct->components INTO DATA(ls_comp).
ASSIGN COMPONENT ls_comp-name OF STRUCTURE <fs_segment>
TO FIELD-SYMBOL(<fs_value>).
IF sy-subrc = 0.
WRITE: / ls_comp-name, '=', <fs_value>.
ENDIF.
ENDLOOP.
CATCH cx_sy_move_cast_error.
" Unknown segment
ENDTRY.
ENDLOOP.

Sending IDoc via RFC

DATA: lt_edidc TYPE TABLE OF edidc40,
lt_edidd TYPE TABLE OF edidd40.
" Build control and data records...
" Send IDoc to RFC destination
CALL FUNCTION 'IDOC_INBOUND_ASYNCHRONOUS'
DESTINATION 'RFC_DEST_TARGET'
TABLES
idoc_control_rec_40 = lt_edidc
idoc_data_rec_40 = lt_edidd
EXCEPTIONS
system_failure = 1
communication_failure = 2.
IF sy-subrc = 0.
WRITE: / 'IDoc sent successfully'.
ELSE.
WRITE: / 'Error sending IDoc'.
ENDIF.

IDoc Serialization

" Serialization for dependent IDocs
DATA: lt_serial TYPE TABLE OF bdi_ser.
" Define serialization object
APPEND VALUE #(
session = '001'
rcvpor = 'SAPEDI'
rcvprt = 'LS'
rcvprn = 'TARGET'
mestyp = 'ORDERS'
serial = 'ORDERS_SERIAL'
) TO lt_serial.
" Send IDoc with serialization
CALL FUNCTION 'IDOC_INBOUND_ASYNCHRONOUS'
TABLES
idoc_control_rec_40 = lt_edidc
idoc_data_rec_40 = lt_edidd
idoc_serialization = lt_serial.

IDoc Status Overview

StatusDescriptionDirection
01IDoc createdOutbound
03IDoc passed to portOutbound
30IDoc ready for transferOutbound
50IDoc added to applicationInbound
51Application document not postedInbound
53Application document postedInbound
56IDoc with EDI syntax errorInbound

Best Practices

  1. Error handling: Write meaningful status messages
  2. Monitoring: Use transaction WE02/WE05 for IDoc monitoring
  3. Performance: Implement mass processing with packages
  4. Serialization: Ensure order for dependent IDocs
  5. Archiving: Regularly archive old IDocs (SARA)
  6. Testing: WE19 for single test, BD87 for reprocessing

Important Transactions

TransactionDescription
WE02/WE05IDoc Display
WE19IDoc Test Environment
WE20Partner Agreements
WE21Ports
BD54Logical Systems
BD64Distribution Model
BD87IDoc Reprocessing