Skip to Content

Suppose for a change request you do some changes and save it in a TR. During a later period, say during the TR review before releasing it, you find out that you had saved the objects in an incorrect TR. Now to correct this we generally follow the below method.

Lets assume TR1 is the incorrect TR. TR2 is the correct TR.

  1. You can go to the transaction se01, enter the TR1 and click enter (session 1).
  2. Open another session and enter the transaction se01. Give the correct TR number(TR2) and press enter (session 2). Click on the edit mode.
  3. Copy the objects from the incorrect TR  to the correct TR manually.
  4. Alternately if all the objects from TR1 are to be copied, you can simply go to TR2, click on the import button, give TR1 in the popup box and click on the tick mark. This will import all the objects from TR1 to TR2 and thus avoiding step1, step2, step3.
  5. Now that the objects are copied into TR2, we have to lock the objects in it.
  6. For this, we first have to unlock the objects in TR1 and only then the objects will get locked in TR2.
  7. Here we have two ways to do it.
    • One way is to go to SE01 transaction and enter TR1. Click on the edit button. The TR comes into the edit mode. Select all the objects that are saved incorrectly and click on the delete button and save the changes.
      • Now, open a new session of SE01 and enter TR2. Click on the edit button. Select the objects in the TR, click on the lock button and save the changes.
    • Another way, is using the standard report RSWBO099. Give the TR/task number in which the objects are to be unlocked and click on execute. Please note that this report will unlock all the objects of the task/TR.
      • Now, open a new session of SE01 and enter TR2. Click on the edit button. Select the objects in the TR, click on the lock button and save the changes.

This becomes a really tedious job in cases where we have huge number of TR’s to be corrected or if there are many objects in the TR. Hence To eliminate the above steps and as a part of automation of the process, I had written the below code.

REPORT zcopy_tr_objects.
TABLES:e071.

TYPES: BEGIN OF ty_output,
         tr_no      TYPE trkorr,
         reason(60) TYPE c,
       END OF ty_output.

**Internal Tables
DATA: tb_tr_object TYPE STANDARD TABLE OF ko200,
      tb_output    TYPE STANDARD TABLE OF ty_output.

**Workareas
DATA: wa_tr_object TYPE ko200,
      wa_output    TYPE ty_output,
      gs_request   TYPE trwbo_request.

**Workfields
DATA: wf_subrc TYPE  sysubrc,
      wf_title TYPE lvc_title.

**Objects
DATA:gr_alv	      TYPE REF TO cl_salv_table,
     gr_columns   TYPE REF TO cl_salv_columns_table,
     obj_header   TYPE REF TO cl_salv_form_layout_grid,
     obj_label    TYPE REF TO cl_salv_form_label,
     wf_functions TYPE REF TO cl_salv_functions_list,
     wf_column    TYPE REF TO cl_salv_column_table.

CLEAR: tb_tr_object, tb_output,
       wa_tr_object, wa_output, gs_request,
       gr_alv, gr_columns, obj_header, obj_label,
       wf_subrc, wf_title, wf_functions, wf_column.

**Selection Screen
SELECT-OPTIONS: s_trlist FOR e071-trkorr.
PARAMETERS: pa_trdst TYPE trkorr.

**Defining ranges for the selection screen
DATA:  wa_trlist LIKE LINE OF s_trlist,
       ra_trlist TYPE RANGE OF trkorr.

**DATA: e_t_msg   TYPE  rs_t_msg,
**      e_request TYPE  trkorr.

AT SELECTION-SCREEN.
  IF s_trlist IS INITIAL.
    MESSAGE 'Pleaes enter the TR/Tasks' TYPE 'E'.
  ENDIF.

  IF pa_trdst IS INITIAL.
    MESSAGE 'The destination TR is mandatory' TYPE 'E'.
  ENDIF.

**Place a special check here with popup confirming that
**the tasks have to be copied

START-OF-SELECTION.
  CLEAR wa_trlist.
  LOOP AT s_trlist INTO wa_trlist.
    IF wa_trlist-low IS NOT INITIAL AND
       wa_trlist-high IS NOT INITIAL.
      DATA(wf_option) = 'BT'.
    ELSE.
      wf_option = 'EQ'.
    ENDIF.

    APPEND VALUE #( sign    = 'I'
                    option  = wf_option
                    low     = wa_trlist-low
                    high    = wa_trlist-high ) TO ra_trlist.
    CLEAR wa_trlist.
  ENDLOOP.

  SELECT * FROM e071
           INTO TABLE @DATA(tb_e071)
           WHERE trkorr IN @ra_trlist.
  IF sy-subrc IS INITIAL.
    SORT tb_e071 BY trkorr.
    DATA(tb_e071_temp) = tb_e071.
    DELETE ADJACENT DUPLICATES FROM tb_e071_temp COMPARING trkorr.
  ENDIF.

  LOOP AT tb_e071_temp ASSIGNING FIELD-SYMBOL(<fs_e071_temp>).

    CALL FUNCTION 'ENQUEUE_E_TRKORR'
      EXPORTING
        trkorr       = <fs_e071_temp>-trkorr
      EXCEPTIONS
        foreign_lock = 1.
    IF sy-subrc  =  1.
      CLEAR wa_output.
      wa_output-tr_no =  <fs_e071_temp>-trkorr.
      CONCATENATE 'Request is currently being edited by' sy-uname INTO wa_output-reason
                                                                  SEPARATED BY space.
      APPEND wa_output TO tb_output.
      CONTINUE.
    ENDIF.

    CLEAR: wa_tr_object,
           tb_tr_object.
    LOOP AT tb_e071 ASSIGNING FIELD-SYMBOL(<fs_e071>)
                    WHERE trkorr = <fs_e071_temp>-trkorr.
      MOVE-CORRESPONDING <fs_e071> TO wa_tr_object.
      APPEND wa_tr_object TO tb_tr_object.
      CLEAR wa_tr_object.
    ENDLOOP.

    DELETE tb_tr_object WHERE pgmid = 'CORR'.

    CLEAR gs_request.
    gs_request-h-trkorr = <fs_e071_temp>-trkorr.
    CALL FUNCTION 'TR_READ_REQUEST'
      EXPORTING
        iv_read_e070       = 'X'
        iv_read_e07t       = 'X'
        iv_read_e070c      = 'X'
        iv_read_e070m      = 'X'
        iv_read_objs_keys  = ' '
        iv_read_attributes = ' '
      CHANGING
        cs_request         = gs_request
      EXCEPTIONS
        error_occured      = 1
        OTHERS             = 2.

    IF sy-subrc <> 0.
      CALL FUNCTION 'DEQUEUE_E_TRKORR'
        EXPORTING
          trkorr = <fs_e071_temp>-trkorr.

      CLEAR wa_output.
      wa_output-tr_no =  <fs_e071_temp>-trkorr.
      wa_output-reason = 'Request could not be read. Please check the TR status'.
      APPEND wa_output TO tb_output.
      CONTINUE.
    ENDIF.

    CALL FUNCTION 'TRINT_UNLOCK_REQUEST'
      EXPORTING
        iv_safe_mode           = ' '
*       iv_set_to_released     = gs_setrel "if set, then this will release the task/TR given
*      IMPORTING
*       ev_cnt_removed_locks   = lv_number "this will give the number of objects that the system has ulocked
      CHANGING
        cs_request             = gs_request
      EXCEPTIONS
        db_access_error        = 1
        object_enqueues        = 2
        no_authority           = 3
        request_not_changeable = 4
        OTHERS                 = 5.
    IF sy-subrc <> 0.
      CLEAR wa_output.
      wa_output-tr_no =  <fs_e071_temp>-trkorr.
      wa_output-reason = 'Request could not be unlocked'.
      APPEND wa_output TO tb_output.
      CONTINUE.
    ELSE.
      CALL FUNCTION 'DEQUEUE_E_TRKORR'
        EXPORTING
          trkorr = <fs_e071_temp>-trkorr.
    ENDIF.

**This FM will lock the objects
    CALL FUNCTION 'RS_TR_WRITE_OBJECTS_TO_REQUEST'
      EXPORTING
        i_t_tr_object      = tb_tr_object
        i_request          = pa_trdst
        i_write_on_request = 'X'
      IMPORTING
*       e_t_msg            = e_t_msg "this will log the messages in case of any error
        e_subrc            = wf_subrc.
    "In case you do not pass any value in i_request, then system will ask
    "for a new to be entered. That TR will be passed here.
*        e_request          = e_request.

    IF wf_subrc IS NOT INITIAL.
      CLEAR wa_output.
      wa_output-tr_no =  <fs_e071_temp>-trkorr.
      wa_output-reason = 'Ojects of the Request could not be locked'.
      APPEND wa_output TO tb_output.
      CONTINUE.
    ENDIF.
  ENDLOOP.

END-OF-SELECTION.
  IF tb_output IS INITIAL.
    WRITE 'The TR/Tasks are successfully copied'.
  ELSE.
*Call method to display the result
    TRY.
        cl_salv_table=>factory(

          IMPORTING r_salv_table = gr_alv
           CHANGING t_table      = tb_output ).
      CATCH cx_salv_msg.
        EXIT.
    ENDTRY.

*Get Columns for the output table
    gr_columns = gr_alv->get_columns( ).

*Changing the columns
*  change_columns( im_alv = gr_alv ).
    wf_functions = gr_alv->get_functions( ).
    wf_functions->set_all( ).

    CLEAR: wf_title.
    wf_title = 'Task/TR whose objects could not be transferred to the destination TR'.
* Setting the top of page.
    CREATE OBJECT obj_header.
    obj_label = obj_header->create_label( row = 1 column = 1 ).
    obj_label->set_text( wf_title ).
    gr_alv->set_top_of_list( obj_label ).

** Set Column properties
    TRY.
        wf_column ?= gr_columns->get_column( 'TR_NO' ).
        wf_column->set_output_length( 15 ).
        wf_column->set_long_text( 'TR Number' ).
      CATCH cx_salv_not_found.
        EXIT.
    ENDTRY.
    TRY.
        wf_column ?= gr_columns->get_column( 'REASON' ).
        wf_column->set_output_length( 60 ).
        wf_column->set_long_text( 'Reason' ).
      CATCH cx_salv_not_found.
        EXIT.
    ENDTRY.

*Displaying the result
    gr_alv->display( ).
  ENDIF.

 

The selection screen:

 

Thanks,
Ankush Devnoorkar.

 

To report this post you need to login first.

7 Comments

You must be Logged on to comment or reply to a post.

  1. Michelle Crapo

    Very nice! I’ve done that before.  Part of my objects in one TR and part in another.  It is a pain – and I fixed it manually.  I’ve also used an object that wasn’t ready yet in someone else’s TR.  Then have to fix that one manually too.  I think the utility will work nicely for the first example.  I might still have to manually work on the second one.

    Michelle

    (1) 
  2. Suhas Saha

    Lets assume TR1 is the incorrect TR. TR2 is the correct TR.

    If i understand correctly, you want to merge the contents of TR1(incorrect) into TR2(correct).

    Then standard transport functionality provides this functionality (Utilities > Reorganize > Merge Requests)

    Is this functionality available in your system? Did you try this out?

    BR, Suhas

    (0) 
    1. Ankush Devnoorkar Post author

      Hi Suhas,

      Thanks for the inputs, but there were a few limitations using the merge functionality.
      1) We cannot perform this in mass. Suppose there are 3-4 TRs to be imported, then we will have to do it one by one.
      2) The merge process will completely delete the TR1. But in case, TR1 is a valid TR which has some other CR changes and we want only a few objects to be copied, as rightly pointed out by Serigo below, in those cases merge option will not be beneficial to us.
      3) We wanted to use a piece of code as a part of the automation process for a tool which could not have been possible with the merge option.

      Thanks,
      Ankush.

      (1) 
  3. Sergio Fraga

    Hello,

     

    I think with method that Suhas suggests TR1 (origin) will be deleted after the merge. If you only want to reassign small set of objects in TR1 to TR2 you cannot you the merge technique.

    Nice initiative Ankush.

    You should consider abapGit to share your code.

    BR,

    Sérgio Fraga

    (1) 
  4. Thomas Zloch

    From the blog text and some comments so far I understood that your code would allow copying selected objects from one TR to another. However I cannot find that part in your code, it seems to always copy all objects from the source TR. Am I wrong?

    Also, wouldn’t it make sense to remove the copied objects from the source TR after unlocking them there, i.e. moving instead of just copying?

    Then also include E071K type keys (without the locking part of course) and this would make up a nice tool. Only to be used if you know what you are doing 😉

     

    (2) 

Leave a Reply