Los IDocs (Intermediate Documents) son el formato estandar de SAP para el intercambio electronico de datos (EDI). Permiten la comunicacion asincrona entre sistemas SAP y socios externos.
Estructura IDoc
| Componente | Descripcion |
|---|---|
| Control Record | Informacion de control (EDIDC) |
| Data Records | Datos utiles en segmentos (EDIDD) |
| Status Records | Estado de procesamiento (EDIDS) |
Tipos IDoc y Message-Types
| Elemento | Transaccion | Descripcion |
|---|---|---|
| Tipo IDoc | WE30 | Estructura de los datos |
| Message-Type | WE81 | Proceso de negocio |
| Segmento | WE31 | Contenedor de datos |
| Partner | WE20 | Socio de comunicacion |
Ejemplos basicos
Crear IDoc manualmente
DATA: lt_edidc TYPE TABLE OF edidc, ls_edidc TYPE edidc, lt_edidd TYPE TABLE OF edidd, ls_edidd TYPE edidd.
" Llenar Control Recordls_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 - Cabecerals_edidd-segnam = 'E1EDK01'.ls_edidd-sdata = 'Datos cabecera pedido...'.APPEND ls_edidd TO lt_edidd.
" Data Segment E1EDP01 - Posicionls_edidd-segnam = 'E1EDP01'.ls_edidd-sdata = 'Datos de posicion...'.APPEND ls_edidd TO lt_edidd.
" Crear IDocCALL FUNCTION 'IDOC_INBOUND_ASYNCHRONOUS' TABLES idoc_control_rec_40 = lt_edidc idoc_data_rec_40 = lt_edidd.Llenar IDoc con estructura
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. " Asignacion de estructura
APPEND ls_edidd TO lt_edidd.Leer y analizar 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.
" Leer Control RecordSELECT SINGLE * FROM edidc INTO ls_edidc WHERE docnum = lv_docnum.
" Leer Data RecordsSELECT * FROM edid4 INTO TABLE lt_edidd WHERE docnum = lv_docnum ORDER BY segnum.
" Leer Status RecordsSELECT * 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.
" Parametros Master-IDocls_master_idoc-mestyp = 'MATMAS'.ls_master_idoc-idoctp = 'MATMAS05'.ls_master_idoc-rcvprt = 'LS'.ls_master_idoc-rcvprn = 'CLNT800'.
" Disparar envio IDocCALL 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 creado:', ls_comm-docnum. ENDLOOP.ENDIF.Establecer estado IDoc
DATA: lt_status TYPE TABLE OF bdidocstat, ls_status TYPE bdidocstat.
ls_status-docnum = lv_docnum.ls_status-status = '53'. " Application document postedls_status-msgty = 'S'.ls_status-msgid = 'E0'.ls_status-msgno = '000'.ls_status-msgv1 = 'Procesado exitosamente'.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.Modulo de funciones Inbound para tipo IDoc propio
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). " Procesar datos IDoc 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.
" Crear pedido TRY. " Logica de negocio aqui
" Estado de exito 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). " Estado de error 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.Configurar distribucion ALE
" Leer modelo de distribucionDATA: 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: / 'Receptor:', ls_receiver-rcvprn.ENDLOOP.Seleccionar y evaluar 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') " Estados de error 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.Reprocesar 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. " Reprocesar 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 Pointer para creacion de IDoc
" Activar Change Pointer (BD52/BD61)" BD50: Message-Type <-> Objeto" BD52: Change Pointer activo
" Crear Change Pointer manualmenteDATA: 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.
" Procesar Change Pointer (RBDMIDOC)CALL FUNCTION 'RBDMIDOC' EXPORTING mestyp = 'MATMAS'.Procesar datos de segmento con estructura
" Mapeo dinamico de segmentoDATA: lo_struct TYPE REF TO cl_abap_structdescr.
LOOP AT lt_edidd INTO DATA(ls_segment). " Determinar estructura para el segmento 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>).
" Transferir datos <fs_segment> = ls_segment-sdata.
" Procesar campos 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. " Segmento desconocido ENDTRY.ENDLOOP.Enviar IDoc via RFC
DATA: lt_edidc TYPE TABLE OF edidc40, lt_edidd TYPE TABLE OF edidd40.
" Construir Control y Data Records...
" Enviar IDoc a RFC-DestinationCALL 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 enviado exitosamente'.ELSE. WRITE: / 'Error en envio'.ENDIF.Serializacion IDoc
" Serializacion para IDocs dependientesDATA: lt_serial TYPE TABLE OF bdi_ser.
" Definir objeto de serializacionAPPEND VALUE #( session = '001' rcvpor = 'SAPEDI' rcvprt = 'LS' rcvprn = 'TARGET' mestyp = 'ORDERS' serial = 'ORDERS_SERIAL') TO lt_serial.
" Enviar IDoc con serializacionCALL FUNCTION 'IDOC_INBOUND_ASYNCHRONOUS' TABLES idoc_control_rec_40 = lt_edidc idoc_data_rec_40 = lt_edidd idoc_serialization = lt_serial.Resumen de estados IDoc
| Estado | Descripcion | Direccion |
|---|---|---|
| 01 | IDoc creado | Outbound |
| 03 | IDoc transferido a puerto | Outbound |
| 30 | IDoc listo para transmision | Outbound |
| 50 | IDoc agregado a aplicacion | Inbound |
| 51 | Documento aplicacion no contabilizado | Inbound |
| 53 | Documento aplicacion contabilizado | Inbound |
| 56 | IDoc con error de sintaxis EDI | Inbound |
Mejores practicas
- Manejo de errores: Escribir mensajes de estado descriptivos
- Monitoreo: Transaccion WE02/WE05 para supervision IDoc
- Rendimiento: Implementar procesamiento masivo con paquetes
- Serializacion: Asegurar secuencia en IDocs dependientes
- Archivado: Archivar IDocs antiguos regularmente (SARA)
- Testing: WE19 para prueba individual, BD87 para reprocesamiento
Transacciones importantes
| Transaccion | Descripcion |
|---|---|
| WE02/WE05 | Visualizar IDoc |
| WE19 | Entorno de prueba IDoc |
| WE20 | Acuerdos de partner |
| WE21 | Puertos |
| BD54 | Sistemas logicos |
| BD64 | Modelo de distribucion |
| BD87 | Reprocesamiento IDoc |
Temas relacionados
- Desarrollo BAPI - Interfaces sincronas
- RFC y Destinations - Remote Function Calls
- Procesamiento XML - Formatos alternativos
- Background Jobs - Procesamiento asincrono