Traitement IDoc ABAP : Intermediate Documents pour la communication EDI

Catégorie
ABAP-Statements
Publié
Auteur
Johannes

Les IDocs (Intermediate Documents) sont le format standard de SAP pour l’échange de données électroniques (EDI). Ils permettent la communication asynchrone entre les systèmes SAP et les partenaires externes.

Structure IDoc

ComposantDescription
Control RecordInformations de contrôle (EDIDC)
Data RecordsDonnées utiles dans les segments (EDIDD)
Status RecordsStatut de traitement (EDIDS)

Types IDoc et Message-Types

ÉlémentTransactionDescription
Type IDocWE30Structure des données
Message-TypeWE81Processus métier
SegmentWE31Conteneur de données
PartnerWE20Partenaire de communication

Exemples de base

Créer manuellement un IDoc

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.

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

Lire et analyser 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.
" 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 via 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.

Définir le statut IDoc

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.

Module fonction Inbound pour type IDoc propre

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.

Configurer la distribution ALE

" 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.

Sélectionner et évaluer les 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') " 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.

Retraiter 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.
" 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 pour la création IDoc

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

Traiter les données de segment avec structure

" 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.

Envoyer IDoc par RFC

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.

Sérialisation IDoc

" 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.

Aperçu des statuts IDoc

StatutDescriptionDirection
01IDoc crééOutbound
03IDoc transmis au portOutbound
30IDoc prêt pour transmissionOutbound
50IDoc ajouté à l’applicationInbound
51Document application non comptabiliséInbound
53Document application comptabiliséInbound
56IDoc avec erreur de syntaxe EDIInbound

Bonnes pratiques

  1. Gestion des erreurs : Écrire des messages de statut explicites
  2. Monitoring : Transaction WE02/WE05 pour la surveillance IDoc
  3. Performance : Implémenter le traitement de masse avec packages
  4. Sérialisation : Assurer l’ordre pour les IDocs dépendants
  5. Archivage : Archiver régulièrement les anciens IDocs (SARA)
  6. Testing : WE19 pour test individuel, BD87 pour post-traitement

Transactions importantes

TransactionDescription
WE02/WE05Affichage IDoc
WE19Environnement de test IDoc
WE20Accords de partenariat
WE21Ports
BD54Systèmes logiques
BD64Modèle de distribution
BD87Post-traitement IDoc

Thèmes connexes