Thursday, April 27, 2017

SAP IDOC Part 2

It’s very long since I have worked something related to Idocs.  Recently while going through a presentation I came across some IDOC related terms and they sounded very new to me. So I thought its time to update my IDOC knowledge. Hope it will be helpful for you too.

As we all know all of the SAP components never lie on the same system because of many reasons like load balancing security issues. So we work in a distributed system environment. So sometimes there is a need to send some data from one SAP system to another SAP system.  Similarly data needs to flow from SAP system to Non SAP system.

For example:
A user places an order in Customer Portal so the same data needs to flow to the Distributor and the Manufacturer. And all might be using different ERP systems.

These systems send and accept data through some specified data container file and this is nothing but IDOC or intermediate document.

ALE supports distributed yet integrated process across several SAP systems.EDI is used for exchange of business document between systems of business partners. IDOC is the data container file which is used for data exchange by both EDI and ALE.

Example:
I have 2 SAP systems DEV1 and DEV2. I have two database tables YTEST_CUSTOMER and YTEST_CUSTITEM. These tables exist in both the systems DEV1 as well as DEV2.
Now my aim is to send data from  DEV1, to DEV2.

Procedure:

IDOC steps are very generic.

Sender system steps: OUTBOUND IDOC



1.       Create/Choose Segments  : WE31
Segments are nothing but the structures in which format we intend to send the data.
2.       Create IDOC type : WE30
IDOC type or Basic type holds the segments in a sequential manner
3.       Create Logical message : WE81
An IDOC type is always implemented in a logical message. WE82
4.       Define Logical system for both source and destination  :  SALE
Logical systems are nothing but symbolic system names that we intend to connect. Assign the logical systems to the respective clients.
5.       RFC Connection : SM59
The name should be same as destination system name. Give the server IP address and system number and check for connectivity.
6.       RFC port : WE21
7.       Create model view : BD64
Specify sender and receiver systems. Generate partner profile from environment. Or create using BD82 or WE20. Add the message type in source and destination logical system in the partner profile. Then distribute the model view.

So now through port following connection is established
Port ->destination system ->Message Type->Basic type ->Segments

8.       Write ABAP code at standalone report or specified points to create an IDOC. Same will be achieved though the function module ‘MASTER_IDOC_DISTRIBUTE’ followed by DB_COMMIT, DEQUEUE_ALL and COMMIT WORK.
9.       Check status of the generated IDOC from WE02
10.   If status is ready for dispatch (Status 30) then run report RSEOUT00 to send the IDOC (Status 03) . Else correct the errors till status is ready for dispatch.

Receiving system steps: INBOUND IDOC



1.       Create Segments, IDOC type, Message type, Sender logical system, RFC destination, Port and sender partner profile and add the message type to profile.
2.       Create a function module to read IDOC data based on segments and use the data for required data base operations.
3.       Assign FM to Logical message (message type and basic type)  WE57
4.       Define input method for FM : BD51
5.       Create Process code : WE42
Choose the function module, Assign Logical message to it.
6.       If all the settings are correct then once IDOC sent from sender system it comes to receiver system and can be viewed from WE02
7.       If errors are found and rectified then the same can be reprocessed through BD84
8.       There are other reports like RBDAPP01, RBDMANI2 for reprocessing inbound IDOC.
9.       To debug  the function module use WE19
10.   Correct and reprocess till status is 53 (Application Document posted)


When an outbound EDI or ALE is executed an IDOC is created. Data in it stored in character format instead of binary format.

An IDOC will have

1.       Control record holding direction, status, basic type, message type, partner ports which are maily for administrative purpose. Remains in EDID2, EDID4 and of type EDIDC.
2.       Data Records which holds the application data in segments. This is of type EDIDD.
3.       Status records holding the status information.  Type EDIDS.
·         IDOC message flows are configured in Distribution model (Sender & Receiver). Each connection on server is represented by recipient or Logical system. Each system is associated with a tRFC port which bound to RFC destination.
·         TRFC is used by ALE and File port is used by EDI.
·         IDOCs can’t be deleted but status can be changed through program RCL_IDOC_SET_STATUS.
·         Statuses are monitored in BD87.
·         Some important Message types: MATMAS, CREMAS, DEBMAS (material, vendor, customer).
·         Whole documentation after settings can be viewed from WE60


Step By Step Screen Shots:



Sample Outbound Program:


*&---------------------------------------------------------------------*
*& Report  YTEST_IDOC1
*&
*&---------------------------------------------------------------------*
***********************************************************************
* Developed By Debesh
***********************************************************************
* Generats an Idoc for Customer Data
***********************************************************************


REPORT ytest_idoc1.
TABLES : ytest_customer.
DATA : ls_ctrl_rec LIKE edidc, "Idoc Control Record
ls_segment1 LIKE zdev_customer,
ls_segment2 LIKE zdev_customeritem.

DATA : lt_customers TYPE STANDARD TABLE OF ytest_customer,
ls_customers TYPE ytest_customer.
DATA : lt_customeritem TYPE STANDARD TABLE OF ytest_custitem,
ls_customeritem TYPE ytest_custitem.

DATA : lt_edidd TYPE STANDARD TABLE OF edidd ,
ls_edidd TYPE edidd.
DATA : lt_comm_idoc TYPE STANDARD TABLE OF edidc,
ls_comm_idoc TYPE edidc .
"Generated Communication IDOc


CONSTANTS :
c_segment1 LIKE edidd-segnam VALUE 'ZDEV_CUSTOMER',
c_segment2 LIKE edidd-segnam VALUE 'ZDEV_CUSTOMERITEM'.

CONSTANTS: c_idoctp LIKE edidc-idoctp VALUE 'YDEV_SHOP'.



*** Selection Screen
SELECT-OPTIONS : cnumber FOR ytest_customer-cnumber .

PARAMETERS : c_mestyp LIKE edidc-mestyp DEFAULT 'YDEV_SHOPMSG', "Message Type
c_rcvprt LIKE edidc-rcvprt DEFAULT 'LS', "Partner type of receiver
c_logsys LIKE edidc-rcvprn DEFAULT 'YDEV_TRG',
c_rcvpor LIKE edidc-rcvpor DEFAULT 'YDEV_PORT',
c_sndprn LIKE edidc-sndprn DEFAULT 'YDEV_SRC',
c_sndprt LIKE edidc-sndprt DEFAULT 'LS'.
*Destination System

***START-OF-SELECTION
START-OF-SELECTION.
PERFORM generate_data_records.
PERFORM generate_control_record.
PERFORM send_idoc.



***********************************************************************

*&---------------------------------------------------------------------*
*& Form generate_data_records
*&---------------------------------------------------------------------*
FORM generate_data_records .
PERFORM get_customer.
PERFORM get_customer_item.
PERFORM arrange_data_records.
ENDFORM. " generate_data_records



*&---------------------------------------------------------------------*
*& Form GET_CUSTOMER
*&---------------------------------------------------------------------*
FORM get_customer.
SELECT *
FROM ytest_customer
INTO CORRESPONDING FIELDS OF TABLE lt_customers
WHERE cnumber IN cnumber.
IF sy-subrc NE 0.
MESSAGE e398(00) WITH 'No Customers Found'.
ENDIF.
ENDFORM. " GET_CUSTOMER



*&---------------------------------------------------------------------*
*& Form GET_CUSTOMER_ITEM
*&---------------------------------------------------------------------*
FORM get_customer_item.
SELECT *
FROM ytest_custitem
INTO CORRESPONDING FIELDS OF TABLE lt_customeritem.
IF sy-subrc NE 0.
MESSAGE i398(00) WITH 'No item found found'.
ENDIF.
ENDFORM. " GET_CUSTOMER_ITEM
*&---------------------------------------------------------------------*
*& Form generate_control_record
*&---------------------------------------------------------------------*
FORM generate_control_record .
ls_ctrl_rec-rcvpor = c_rcvpor. "Receiver Port
ls_ctrl_rec-mestyp = c_mestyp. "Message type
ls_ctrl_rec-idoctp = c_idoctp. "Basic IDOC type
ls_ctrl_rec-rcvprt = c_rcvprt. "Partner type of receiver
ls_ctrl_rec-rcvprn = c_logsys. "Partner number of receiver

ls_ctrl_rec-sndprt = c_sndprt. "Sender Partner type
ls_ctrl_rec-sndprn = c_sndprn. "Sender Partner Number
ENDFORM. " generate_control_record



*&---------------------------------------------------------------------*
*& Form send_idoc
*&---------------------------------------------------------------------*
FORM send_idoc.
CALL FUNCTION 'MASTER_IDOC_DISTRIBUTE'
EXPORTING
master_idoc_control = ls_ctrl_rec
TABLES
communication_idoc_control = lt_comm_idoc
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.
MESSAGE ID sy-msgid TYPE sy-msgty NUMBER sy-msgno
WITH sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4.
ELSE.
* COMMIT WORK.
CALL FUNCTION 'DB_COMMIT'.
CALL FUNCTION 'DEQUEUE_ALL'.
COMMIT WORK.
LOOP AT lt_comm_idoc INTO ls_comm_idoc.
WRITE:/ 'IDoc Generated - ', ls_comm_idoc-docnum.
ENDLOOP.
ENDIF.
ENDFORM. " send_idoc



*&---------------------------------------------------------------------*
*& Form arrange_data_records
*&---------------------------------------------------------------------*
FORM arrange_data_records .
DATA: w_index1 LIKE sy-tabix,
w_index2 LIKE sy-tabix.
SORT lt_customers BY cnumber.
SORT lt_customeritem BY cnumber .

LOOP AT lt_customers INTO ls_customers.


CLEAR w_index1.
READ TABLE lt_customeritem INTO ls_customeritem WITH KEY cnumber = ls_customers-cnumber BINARY SEARCH.

IF sy-subrc = 0.
w_index1 = sy-tabix.
LOOP AT lt_customeritem INTO ls_customeritem FROM w_index1.
IF ls_customeritem-cnumber NE ls_customers-cnumber.
EXIT.
ENDIF.
ls_segment2-vgpos = ls_customeritem-vgpos.
ls_segment2-ntgew = ls_customeritem-ntgew.
ls_segment2-netwr = ls_customeritem-netwr.
ls_segment2-cnumber = ls_customeritem-cnumber.
ls_edidd-segnam = c_segment2.
ls_edidd-sdata = ls_segment2.
APPEND ls_edidd TO lt_edidd.
CLEAR ls_edidd.

CLEAR w_index2.
ls_segment1-cnumber = ls_customers-cnumber.
ls_segment1-name = ls_customers-name.
ls_segment1-contact = ls_customers-contact.
ls_edidd-segnam = c_segment1.
ls_edidd-sdata = ls_segment1.
APPEND ls_edidd TO lt_edidd.
CLEAR ls_edidd.
ENDLOOP.
ENDIF.

ENDLOOP.
ENDFORM. " arrange_data_records



Sample Inbound Function Module:


FUNCTION YTEST_IODC_RECEIVE.
*"----------------------------------------------------------------------
*"*"Local Interface:
*" IMPORTING
*" REFERENCE(INPUT_METHOD) TYPE BDWFAP_PAR-INPUTMETHD
*" REFERENCE(MASS_PROCESSING) TYPE BDWFAP_PAR-MASS_PROC
*" EXPORTING
*" REFERENCE(WORKFLOW_RESULT) TYPE BDWF_PARAM-RESULT
*" REFERENCE(APPLICATION_VARIABLE) TYPE BDWF_PARAM-APPL_VAR
*" REFERENCE(IN_UPDATE_TASK) TYPE BDWFAP_PAR-UPDATETASK
*" REFERENCE(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
*" EXCEPTIONS
*" WRONG_FUNCTION_CALLED
*"----------------------------------------------------------------------

** Include File containing ALE constants
INCLUDE MBDCONWF.



data : ls_segment1 type ZDEV_CUSTOMER, "ty_seg1,
ls_segment2 type ZDEV_CUSTOMERITEM. "ty_seg2.


DATA : lT_ytest_customer TYPE STANDARD TABLE OF ytest_customer ,
ls_ytest_customer TYPE ytest_customer .

DATA : lT_ytest_custitem TYPE STANDARD TABLE OF ytest_custitem ,
ls_ytest_custitem TYPE ytest_custitem .



***********************************************************************
WORKFLOW_RESULT = C_WF_RESULT_OK.

LOOP AT IDOC_CONTRL.
IF IDOC_CONTRL-MESTYP NE 'YDEV_SHOPMSG'.
RAISE WRONG_FUNCTION_CALLED.
ENDIF.

* Before reading a new entry, clear application buffer
LOOP AT IDOC_DATA WHERE DOCNUM EQ IDOC_CONTRL-DOCNUM.
CASE IDOC_DATA-SEGNAM.
WHEN 'ZDEV_CUSTOMER'.
ls_segment1 = IDOC_DATA-SDATA.
MOVE-CORRESPONDING ls_segment1 TO ls_ytest_customer.
mODIFY ytest_customer FROM ls_ytest_customer.
WHEN 'ZDEV_CUSTOMERITEM'.
ls_segment2 = IDOC_DATA-SDATA.
MOVE-CORRESPONDING ls_segment2 TO ls_ytest_custitem.

MODIFY Ytest_custITEM FROM ls_ytest_custITEM.

ENDCASE.
ENDLOOP.


IF SY-SUBRC EQ 0.
IDOC_STATUS-DOCNUM = IDOC_CONTRL-DOCNUM.
IDOC_STATUS-STATUS = '53'.
IDOC_STATUS-MSGTY = 'I'.
IDOC_STATUS-MSGID = 'YM'.
IDOC_STATUS-MSGNO = '004'.
IDOC_STATUS-MSGV1 = ls_ytest_customer-Cnumber.
APPEND IDOC_STATUS.
CLEAR IDOC_STATUS.
ELSE.
IDOC_STATUS-DOCNUM = IDOC_CONTRL-DOCNUM.
IDOC_STATUS-STATUS = '51'.
IDOC_STATUS-MSGTY = 'E'.
IDOC_STATUS-MSGID = 'YM'.
IDOC_STATUS-MSGNO = '005'.
IDOC_STATUS-MSGV1 = ls_ytest_customer-cnumber.
APPEND IDOC_STATUS.
CLEAR IDOC_STATUS.
WORKFLOW_RESULT = C_WF_RESULT_ERROR.
RETURN_VARIABLES-WF_PARAM = 'Error_Idocs'.
RETURN_VARIABLES-DOC_NUMBER = IDOC_CONTRL-DOCNUM.
APPEND RETURN_VARIABLES.
CLEAR RETURN_VARIABLES.
ENDIF.
ENDLOOP.




ENDFUNCTION.

IDOC status messages:


If outbound status (1-42)

1. 26 => Syntax error, check segment sequence and other names.

2. 30=>ready for dispatch, run RSEOUT00.



If Inbound Status (50-75)

1. 56=> IDOC with errors, check partner profiles.

2. Run RBDAPP01 after correction

3. Use BD84 to reprocess

4. 60 =>Check segments



51-> Application Document not posted

53->successful

32->manually edited

01->IDOC generated

64->Ready to transfer



IDOC XML Display:


IDOCs is stored in Hierarchical format so its easily gets converted to XML format.



*&---------------------------------------------------------------------*
*& Report YTEST_IDOC_DISPLAY
*&
*&---------------------------------------------------------------------*
*&
*&
*&---------------------------------------------------------------------*

REPORT YTEST_IDOC_DISPLAY.

PARAMETERS: p_idoc TYPE edidd-docnum.

DATA: o_idoc_xml TYPE REF TO cl_idoc_xml1.
DATA: gv_string TYPE string.
DATA: gt_string TYPE TABLE OF string.

*Create IDoc object
CREATE OBJECT o_idoc_xml
EXPORTING
docnum = p_idoc
EXCEPTIONS
OTHERS = 1.
IF sy-subrc NE 0.
WRITE: /'Error while creating idoc object'.
EXIT.
ENDIF.

*Get IDoc data as string
CALL METHOD o_idoc_xml->get_xmldata_as_string
IMPORTING
data_string = gv_string.

APPEND gv_string TO gt_string.

IF sy-subrc NE 0 OR o_idoc_xml IS INITIAL.
WRITE: /'Error while getting xml data as string'.
EXIT.
ENDIF.

*Download IDoc data as XML file
CALL FUNCTION 'GUI_DOWNLOAD'
EXPORTING
filename = 'D:\idoc.xml'
TABLES
data_tab = gt_string.





1 comment:

  1. This is really interesting blog on SAP IDOC Online Training, You are a very skilled blogger. I've joined your rss feed and look forward to seeking more of your excellent post. Also, I've shared your web site in my social networks! Thank You!!!

    ReplyDelete