Procesamiento ABAP IDoc: Documentos intermedios para comunicacion EDI

Kategorie
ABAP-Statements
Veröffentlicht
Autor
Johannes

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

ComponenteDescripcion
Control RecordInformacion de control (EDIDC)
Data RecordsDatos utiles en segmentos (EDIDD)
Status RecordsEstado de procesamiento (EDIDS)

Tipos IDoc y Message-Types

ElementoTransaccionDescripcion
Tipo IDocWE30Estructura de los datos
Message-TypeWE81Proceso de negocio
SegmentoWE31Contenedor de datos
PartnerWE20Socio 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 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 - Cabecera
ls_edidd-segnam = 'E1EDK01'.
ls_edidd-sdata = 'Datos cabecera pedido...'.
APPEND ls_edidd TO lt_edidd.
" Data Segment E1EDP01 - Posicion
ls_edidd-segnam = 'E1EDP01'.
ls_edidd-sdata = 'Datos de posicion...'.
APPEND ls_edidd TO lt_edidd.
" Crear IDoc
CALL 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 Record
SELECT SINGLE * FROM edidc INTO ls_edidc
WHERE docnum = lv_docnum.
" Leer Data Records
SELECT * FROM edid4 INTO TABLE lt_edidd
WHERE docnum = lv_docnum
ORDER BY segnum.
" Leer 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.
" Parametros Master-IDoc
ls_master_idoc-mestyp = 'MATMAS'.
ls_master_idoc-idoctp = 'MATMAS05'.
ls_master_idoc-rcvprt = 'LS'.
ls_master_idoc-rcvprn = 'CLNT800'.
" Disparar envio IDoc
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 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 posted
ls_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 distribucion
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: / '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 manualmente
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.
" Procesar Change Pointer (RBDMIDOC)
CALL FUNCTION 'RBDMIDOC'
EXPORTING
mestyp = 'MATMAS'.

Procesar datos de segmento con estructura

" Mapeo dinamico de segmento
DATA: 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-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 enviado exitosamente'.
ELSE.
WRITE: / 'Error en envio'.
ENDIF.

Serializacion IDoc

" Serializacion para IDocs dependientes
DATA: lt_serial TYPE TABLE OF bdi_ser.
" Definir objeto de serializacion
APPEND VALUE #(
session = '001'
rcvpor = 'SAPEDI'
rcvprt = 'LS'
rcvprn = 'TARGET'
mestyp = 'ORDERS'
serial = 'ORDERS_SERIAL'
) TO lt_serial.
" Enviar IDoc con serializacion
CALL 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

EstadoDescripcionDireccion
01IDoc creadoOutbound
03IDoc transferido a puertoOutbound
30IDoc listo para transmisionOutbound
50IDoc agregado a aplicacionInbound
51Documento aplicacion no contabilizadoInbound
53Documento aplicacion contabilizadoInbound
56IDoc con error de sintaxis EDIInbound

Mejores practicas

  1. Manejo de errores: Escribir mensajes de estado descriptivos
  2. Monitoreo: Transaccion WE02/WE05 para supervision IDoc
  3. Rendimiento: Implementar procesamiento masivo con paquetes
  4. Serializacion: Asegurar secuencia en IDocs dependientes
  5. Archivado: Archivar IDocs antiguos regularmente (SARA)
  6. Testing: WE19 para prueba individual, BD87 para reprocesamiento

Transacciones importantes

TransaccionDescripcion
WE02/WE05Visualizar IDoc
WE19Entorno de prueba IDoc
WE20Acuerdos de partner
WE21Puertos
BD54Sistemas logicos
BD64Modelo de distribucion
BD87Reprocesamiento IDoc

Temas relacionados