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