Register Login

Add New Segment in Inbound Or Outbound IDoc

Updated May 18, 2018

Global class which adds segment to IDoc can be described in two steps

1.    Constructor

·          Reads the IDoc type or extension

·          Checks if the given Basic type or extension is valid or not

·          If the Basic type or extension is valid read the structure using

                                    Function module - > 1. EXTTYPE_READ   (For Extension)

                                                                      2. IDOCTYPE_READ (For Basic type)

·          Fill the class attribute with the structure of basic type or extension

2.    Segment addition method

·          Method will check the hierarchy level at which the new segment must be inserted

·          If segment hierarchy level is greater than 3 then parent segment number is mandatory

·          If parent segment number is given insert segment as a child of it

·          After inserting a segment change segment number and parent segment       number of all the segments which follow the new segment.

·          If the segment is at hierarchy level 2 then check for any other segment with same name.

·          If found then insert the new segment above the existing segment

               Else check the structure of the Idoc from instance attribute.

·          The new segment should be inserted at the correct sequence as per the hierarchy of the Idoc.

1.

ZCL_ADD_IDOC_SEGMENT_TEMP_TEST

Class Interface     

Add new segment in Idoc.

2

ZOTC_SEG_NAME

Table Type

Stores names of the Basic type’s or Extension’s segments.

3

ZOTC_SEG_NAME_STRUC

Structure

Idoc segment name.

Class interface : ZCL_ADD_IDOC_SEGMENT_TEMP_TEST

1.    Properties:

2.    Attributes

 

Table type: ZOTC_SEG_NAME

 

Structure: ZOTC_SEG_NAME_STRUC

 

Methods

 

Method: CONSTRUCTOR (Parameters)

 

Method: Z_ADD_SEGMENT (Parameters)

 

CODE:

Method: CONSTRUCTOR

*------------------------------------------------------------------*
* constructor reads the IDoc type or extension
* Checks if the given Basic type or extension is valid or not
* If the Basic type or extension is valid read the structure using
* Function module - > 1. EXTTYPE_READ   (For Extension)
*                     2. IDOCTYPE_READ  (For Basic type)
* Fill the class attribute with the structure of basic type or extension
*------------------------------------------------------------------*
  DATA: li_segnam   TYPE zotc_seg_name,
        lwa_segnam  TYPE zotc_seg_name_struc,
        lv_lines    TYPE i,
        lv_do_count TYPE i,
        lv_exttyp   TYPE edi_iapi00-cimtyp,
        li_idoc_struc TYPE STANDARD TABLE OF edi_iapi02,
        li_extn_struc TYPE STANDARD TABLE OF edi_iapi06.

  FIELD-SYMBOLS:   TYPE edi_iapi02,
                   TYPE edi_iapi06.

*------------------------------------------------------------------*
* First check if IM_IDOC_NAME contains Basic type
* If IM_IDOC_NAME is a valid Basic type then                        * PT_SYNTAX will have it's
* structure


  CALL FUNCTION 'IDOCTYPE_READ'
    EXPORTING
      pi_idoctyp       = im_idoc_name
      pi_read_devc     = space
    TABLES
      pt_syntax        = li_idoc_struc
    EXCEPTIONS
      object_not_found = 1
      db_error         = 2
      no_authority     = 3
      OTHERS           = 4.
  IF sy-subrc <> 0.


*If IM_IDOC_NAME is not a valid basic type then check if it's
* an extension


    lv_exttyp = im_idoc_name. " resolve type conflict
    CALL FUNCTION 'EXTTYPE_READ'
      EXPORTING
        pi_cimtyp        = lv_exttyp
        pi_read_devc     = space
      TABLES
        pt_int_syntax    = li_extn_struc
      EXCEPTIONS
        object_not_found = 1
        db_error         = 2
        no_authority     = 3
        OTHERS           = 4.
    IF sy-subrc <> 0.
      RAISE idoc_type_does_not_exist.
    ELSE.
*------------------------------------------------------------------*
* Fill the attribute with Idoc structure in reverse order


      DESCRIBE TABLE li_extn_struc LINES lv_lines.
      lv_do_count = lv_lines.
      DO lv_do_count TIMES.
        IF lv_lines = 0.
          EXIT.
        ENDIF.
        READ TABLE li_extn_struc ASSIGNING   INDEX lv_lines.
        IF sy-subrc = 0.
          lwa_segnam-segnam =  -segtyp.
          APPEND lwa_segnam TO li_segnam.
          CLEAR lwa_segnam.
        ENDIF.
        lv_lines = lv_lines - 1.
      ENDDO.
      UNASSIGN  .
      zotc_segnam = li_segnam.
      FREE: li_segnam,li_extn_struc.
      CLEAR lv_do_count.
    ENDIF.
  ELSE.
*------------------------------------------------------------------*
* Fill the attribute with Idoc structure in reverse order


    DESCRIBE TABLE li_idoc_struc LINES lv_lines.
    lv_do_count = lv_lines.
    DO lv_do_count TIMES.
      IF lv_lines = 0.
        EXIT.
      ENDIF.
      READ TABLE li_idoc_struc ASSIGNING   INDEX lv_lines.
      IF sy-subrc = 0.
        lwa_segnam-segnam =  -segtyp.
        APPEND lwa_segnam TO li_segnam.
        CLEAR lwa_segnam.
      ENDIF.
      lv_lines = lv_lines - 1.
    ENDDO.
    UNASSIGN  .
    zotc_segnam = li_segnam.
    FREE: li_segnam,li_idoc_struc.
    CLEAR lv_do_count.
  ENDIF.

Method: Z_ADD_SEGMENT

*------------------------------------------------------------------*
*•  Method will check the hierarchy level at which the new segment 

*must be inserted.
*•  If segment hierarchy level is greater than 3 then parent segment
*       number is mandatory.
*•  If parent segment number is given insert segment as a child of  *it.
*•  After inserting a segment; change segment number and parent 

*segment number of all the segments which follow the new segment.
*•  If the segment is at hierarchy level 2 then check for any other
*       segment with same name.
*•    If found then insert the new segment above the existing 

*segment.
*•    Else check the structure of the Idoc from instance attribute.
*•    The new segment should be inserted at the correct sequence as *per the hierarchy of the Idoc.
*------------------------------------------------------------------*
  TYPES: BEGIN OF t_psgnum_chg ,
             new_psgnum TYPE edi_psgnum,
             old_psgnum TYPE edi_psgnum.
  TYPES: END OF t_psgnum_chg.

  CONSTANTS: lc_1000(4) TYPE c VALUE '1000'.

  DATA: lwa_edidd       TYPE edidd,
        lv_old_psegnum  TYPE edidd-psgnum,
        lv_old_segnum   TYPE edidd-segnum,
        lv_old_h        TYPE edidd-hlevel,
        lv_tabix        TYPE sy-tabix,
        lv_segnam_tabix TYPE sy-tabix,
        lv_tabix_1      TYPE sy-tabix,
        lv_lines        TYPE i,
        lv_segnam       TYPE edidd-segnam,
        li_result_tab   TYPE match_result_tab,
        li_psgnum_chg   TYPE STANDARD TABLE OF t_psgnum_chg,
        lwa_psgnum_chg  TYPE t_psgnum_chg.

  FIELD-SYMBOLS:        TYPE edidd,
                       TYPE zotc_seg_name_struc,
                   TYPE match_result,
                   TYPE t_psgnum_chg.

  IF im_hlevel >= 3 AND im_psgnum IS INITIAL.
* Check for parent segment number. If not given raise an exception
    RAISE parent_segment_not_given.

  ELSEIF im_psgnum IS NOT INITIAL.
*------------------------------------------------------------------*
* Parent segment number given, hence new segment must be inserted
* as a child segment of the appropriate parent

    READ TABLE ch_idoc_data
     ASSIGNING 
      WITH KEY segnum = im_psgnum.

    IF sy-subrc = 0.
*Fill in the Idoc work area for insertion of segment
      lwa_edidd-sdata  = im_sdata.  "Segment data
      lwa_edidd-hlevel = im_hlevel. "Hierarchy level
      lwa_edidd-mandt  = sy-mandt.  "Client
      lwa_edidd-dtint2 = lc_1000.   "Length field for VARC field
      lwa_edidd-psgnum = im_psgnum. "Number of the hierarchically higher SAP segment
      lwa_edidd-segnam = im_segnam. "Number of SAP segment
      lwa_edidd-docnum = im_docnum. "IDoc number
      lwa_edidd-segnum =  -segnum + 1.
      lv_tabix         = sy-tabix + 1.
*Insert Segment
      INSERT lwa_edidd INTO ch_idoc_data INDEX lv_tabix.

      IF sy-subrc = 0.
        ex_segnum = lwa_edidd-segnum.
        UNASSIGN  .
        CLEAR lwa_edidd.
        lv_tabix = lv_tabix + 1.
* After segment insertion increament the segment number of next segments
        LOOP AT ch_idoc_data ASSIGNING   FROM lv_tabix.

* Segment data change should be restricted to single Idoc
* Important check in case of inbound Idoc processing routine is capable
* of processing multiple IDocs at time
          IF  -docnum <> im_docnum.
            EXIT.
          ENDIF.

           -segnum =  -segnum + 1.

* Change parent segment number only if segment number of parent segment
* was incremented
          IF lv_old_h IS NOT INITIAL.
            IF lv_old_h <>  -hlevel AND  -hlevel <> 2.
               -psgnum = lv_old_segnum.
            ELSEIF lv_old_h =  -hlevel AND  -hlevel <> 2.
               -psgnum = lv_old_psegnum.
            ENDIF.
          ENDIF.

          lv_old_psegnum =  -psgnum.
          lv_old_segnum  =  -segnum.
          lv_old_h       =  -hlevel.
        ENDLOOP.
        CLEAR: lv_old_h, lv_old_segnum, lv_old_psegnum, lv_tabix.
        UNASSIGN  .
      ENDIF." sy-subrc for insert
    ENDIF.
*------------------------------------------------------------------*
*Segment to be inserted is not a child of any segment


  ELSEIF im_hlevel = 02 AND im_psgnum IS INITIAL.

*Check if a segment with same name is already present

    READ TABLE ch_idoc_data
     ASSIGNING 
      WITH KEY segnam = im_segnam.

    IF sy-subrc = 0.
* Segment with same name is already present. Insert the new segment
* just above.
* This ensures that hierarchy of Idoc segments are maintained

      lwa_edidd-sdata  = im_sdata.
      lwa_edidd-mandt  = sy-mandt.
      lwa_edidd-dtint2 = lc_1000.
      lwa_edidd-hlevel = im_hlevel.
      lwa_edidd-psgnum = im_psgnum.
      lwa_edidd-segnam = im_segnam.
      lwa_edidd-docnum = im_docnum.
      lv_tabix         = sy-tabix.
      lv_tabix_1       = sy-tabix - 1.

*Calculate the Segment number for new segment dynamically
      IF lv_tabix_1 >= 1.
        READ TABLE ch_idoc_data
         ASSIGNING 
             INDEX lv_tabix_1.
        IF sy-subrc = 0.
          lwa_edidd-segnum =  -segnum + 1.
        ENDIF.
      ENDIF.

      INSERT lwa_edidd INTO ch_idoc_data INDEX lv_tabix.

      IF sy-subrc = 0.
        ex_segnum = lwa_edidd-segnum.
        UNASSIGN  .
        CLEAR lwa_edidd.
        lv_tabix = sy-tabix + 2.

        lv_old_segnum = ex_segnum.

* After segment insertion increament the segment number of next segm*ents
        LOOP AT ch_idoc_data ASSIGNING   FROM lv_tabix.

* Segment data change should be restricted to single Idoc
* Important check in case of inbound Idoc processing routine is capable
* of processing multiple IDocs at time


          IF  -docnum <> im_docnum.
            EXIT.
          ENDIF.

           -segnum = lv_old_segnum + 1.

* Change parent segment number only if segment number of parent segment
* was incremented

          IF lv_old_h IS NOT INITIAL.
            IF lv_old_h <>  -hlevel AND  -hlevel <> 2.
               -psgnum = lv_old_segnum.
            ELSEIF lv_old_h =  -hlevel AND  -hlevel <> 2.
               -psgnum = lv_old_psegnum.
            ENDIF.
          ENDIF.

          lv_old_psegnum =  -psgnum.
          lv_old_segnum  =  -segnum.
          lv_old_h       =  -hlevel.

        ENDLOOP.
        UNASSIGN  .
        CLEAR: lv_old_h, lv_old_segnum, lv_old_psegnum, lv_tabix.
      ENDIF."for INSERT statment

    ELSE.
* Segment with same name is not present.
* Read the Idoc hirachy from INSTATNCE ATTRIBUTE "ME->ZOTC_SEGNAM"
* Insert the new segment at correct hierarchical position

      READ TABLE me->zotc_segnam ASSIGNING 
        WITH KEY segnam = im_segnam.
      IF sy-subrc = 0.
        lv_segnam_tabix = sy-tabix - 1.
        LOOP AT me->zotc_segnam ASSIGNING   FROM lv_segnam_tabix.
          lv_segnam =  .

          LOOP AT ch_idoc_data ASSIGNING 
            WHERE segnam =  .
            lv_tabix         = sy-tabix + 1.
          ENDLOOP.

          IF   IS ASSIGNED.

            lwa_edidd-sdata  = im_sdata.
            lwa_edidd-mandt  = sy-mandt.
            lwa_edidd-dtint2 = lc_1000.
            lwa_edidd-hlevel = im_hlevel.
            lwa_edidd-psgnum = im_psgnum.
            lwa_edidd-segnam = im_segnam.
            lwa_edidd-docnum = im_docnum.
            lwa_edidd-segnum =  -segnum + 1.

            INSERT lwa_edidd INTO ch_idoc_data INDEX lv_tabix.

            IF sy-subrc = 0.

              ex_segnum = lwa_edidd-segnum.
              UNASSIGN  .
              CLEAR lwa_edidd.
              lv_tabix = lv_tabix + 1.

* After segment insertion increament the segment number of next segments

              LOOP AT ch_idoc_data ASSIGNING   FROM lv_tabix.

* Segment data change should be restricted to single Idoc
* Important check in case of inbound Idoc processing routine is capable
* of processing multiple IDocs at time

                IF  -docnum <> im_docnum.
                  EXIT.
                ENDIF.

                 -segnum =  -segnum + 1.

* Change parent segment number only if segment number of parent segment
* was incremented

                IF lv_old_h IS NOT INITIAL.
                  IF lv_old_h <>  -hlevel AND  -hlevel <> 2.
                     -psgnum = lv_old_segnum.
                  ELSEIF lv_old_h =  -hlevel AND  -hlevel <> 2.
                     -psgnum = lv_old_psegnum.
                  ENDIF.
                ENDIF.

                lv_old_psegnum =  -psgnum.
                lv_old_segnum  =  -segnum.
                lv_old_h       =  -hlevel.

              ENDLOOP."AT ch_idoc_data
              UNASSIGN  .
              CLEAR: lv_old_h, lv_old_segnum, lv_old_psegnum.
              IF lv_tabix IS NOT INITIAL.
                CLEAR lv_tabix.
                EXIT.
              ENDIF."lv_tabix IS NOT INITIAL.
              EXIT.
            ENDIF."sy-subrc = 0. for insert
          ENDIF.

        ENDLOOP."AT zotc_segnam.

      ENDIF."READ TABLE zotc_segnam
    ENDIF."READ TABLE ch_idoc_data
  ENDIF.

Thanks & Regards,

A.Uttam


×