ABAP IDoc-Verarbeitung: Intermediate Documents für EDI-Kommunikation

kategorie
ABAP-Statements
Veröffentlicht
autor
Johannes

IDocs (Intermediate Documents) sind SAPs Standardformat für den elektronischen Datenaustausch (EDI). Sie ermöglichen die asynchrone Kommunikation zwischen SAP-Systemen und externen Partnern.

IDoc-Struktur

KomponenteBeschreibung
Control RecordSteuerinformationen (EDIDC)
Data RecordsNutzdaten in Segmenten (EDIDD)
Status RecordsVerarbeitungsstatus (EDIDS)

IDoc-Typen und Message-Types

ElementTransaktionBeschreibung
IDoc-TypWE30Struktur der Daten
Message-TypeWE81Geschäftsprozess
SegmentWE31Datencontainer
PartnerWE20Kommunikationspartner

Grundlegende Beispiele

IDoc manuell erstellen

DATA: lt_edidc TYPE TABLE OF edidc,
ls_edidc TYPE edidc,
lt_edidd TYPE TABLE OF edidd,
ls_edidd TYPE edidd.
" Control Record füllen
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 = 'Bestellkopfdaten...'.
APPEND ls_edidd TO lt_edidd.
" Data Segment E1EDP01 - Position
ls_edidd-segnam = 'E1EDP01'.
ls_edidd-sdata = 'Positionsdaten...'.
APPEND ls_edidd TO lt_edidd.
" IDoc erstellen
CALL FUNCTION 'IDOC_INBOUND_ASYNCHRONOUS'
TABLES
idoc_control_rec_40 = lt_edidc
idoc_data_rec_40 = lt_edidd.

IDoc mit Struktur befüllen

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. " Strukturzuweisung
APPEND ls_edidd TO lt_edidd.

IDoc lesen und analysieren

DATA: lv_docnum TYPE edi_docnum VALUE '0000000000012345',
ls_edidc TYPE edidc,
lt_edidd TYPE TABLE OF edidd,
lt_edids TYPE TABLE OF edids.
" Control Record lesen
SELECT SINGLE * FROM edidc INTO ls_edidc
WHERE docnum = lv_docnum.
" Data Records lesen
SELECT * FROM edid4 INTO TABLE lt_edidd
WHERE docnum = lv_docnum
ORDER BY segnum.
" Status Records lesen
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 über Master-IDoc

DATA: ls_master_idoc TYPE edidc,
lt_comm_idocs TYPE TABLE OF edidc.
" Master-IDoc Parameter
ls_master_idoc-mestyp = 'MATMAS'.
ls_master_idoc-idoctp = 'MATMAS05'.
ls_master_idoc-rcvprt = 'LS'.
ls_master_idoc-rcvprn = 'CLNT800'.
" IDoc-Versand auslösen
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 erstellt:', ls_comm-docnum.
ENDLOOP.
ENDIF.

IDoc-Status setzen

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 = 'Erfolgreich verarbeitet'.
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-Funktionsbaustein für eigenen IDoc-Typ

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).
" IDoc-Daten verarbeiten
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.
" Bestellung anlegen
TRY.
" Business-Logik hier
" Erfolgsstatus
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).
" Fehlerstatus
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.

ALE-Verteilung konfigurieren

" Verteilungsmodell lesen
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: / 'Empfänger:', ls_receiver-rcvprn.
ENDLOOP.

IDocs selektieren und auswerten

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') " Fehler-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.

IDoc erneut verarbeiten

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.
" IDoc erneut verarbeiten
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 Pointer für IDoc-Erstellung

" Change Pointer aktivieren (BD52/BD61)
" BD50: Message-Type <-> Objekt
" BD52: Change Pointer aktiv
" Change Pointer manuell erzeugen
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.
" Change Pointer verarbeiten (RBDMIDOC)
CALL FUNCTION 'RBDMIDOC'
EXPORTING
mestyp = 'MATMAS'.

Segment-Daten mit Struktur verarbeiten

" Dynamisches Segment-Mapping
DATA: lo_struct TYPE REF TO cl_abap_structdescr.
LOOP AT lt_edidd INTO DATA(ls_segment).
" Struktur zum Segment ermitteln
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>).
" Daten übertragen
<fs_segment> = ls_segment-sdata.
" Felder verarbeiten
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.
" Segment unbekannt
ENDTRY.
ENDLOOP.

IDoc per RFC versenden

DATA: lt_edidc TYPE TABLE OF edidc40,
lt_edidd TYPE TABLE OF edidd40.
" Control und Data Records aufbauen...
" IDoc an RFC-Destination senden
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 erfolgreich gesendet'.
ELSE.
WRITE: / 'Fehler beim Versand'.
ENDIF.

IDoc-Serialisierung

" Serialisierung für abhängige IDocs
DATA: lt_serial TYPE TABLE OF bdi_ser.
" Serialisierungsobjekt definieren
APPEND VALUE #(
session = '001'
rcvpor = 'SAPEDI'
rcvprt = 'LS'
rcvprn = 'TARGET'
mestyp = 'ORDERS'
serial = 'ORDERS_SERIAL'
) TO lt_serial.
" IDoc mit Serialisierung versenden
CALL FUNCTION 'IDOC_INBOUND_ASYNCHRONOUS'
TABLES
idoc_control_rec_40 = lt_edidc
idoc_data_rec_40 = lt_edidd
idoc_serialization = lt_serial.

IDoc-Status-Übersicht

StatusBeschreibungRichtung
01IDoc erzeugtOutbound
03IDoc an Port übergebenOutbound
30IDoc bereit zur ÜbertragungOutbound
50IDoc zum Anwendung hinzugefügtInbound
51Anwendungsdokument nicht gebuchtInbound
53Anwendungsdokument gebuchtInbound
56IDoc mit EDI-Syntax-FehlerInbound

Best Practices

  1. Fehlerbehandlung: Aussagekräftige Status-Nachrichten schreiben
  2. Monitoring: Transaktion WE02/WE05 für IDoc-Überwachung
  3. Performance: Massenverarbeitung mit Paketen implementieren
  4. Serialisierung: Bei abhängigen IDocs Reihenfolge sicherstellen
  5. Archivierung: Alte IDocs regelmäßig archivieren (SARA)
  6. Testing: WE19 für Einzeltest, BD87 für Nachverarbeitung

Wichtige Transaktionen

TransaktionBeschreibung
WE02/WE05IDoc-Anzeige
WE19IDoc-Testumgebung
WE20Partnervereinbarungen
WE21Ports
BD54Logische Systeme
BD64Verteilungsmodell
BD87IDoc-Nachverarbeitung

Verwandte Themen