Skip to Content
From previous experiences it has always been a challenge to get the order of transports right during go live time.

You would say just import them into PROD in the same order that they were applied to TEST/QA (from transaction STMS). Easier said than done.

Normally during cutover to TEST/QA a list of transports is prepared which is sorted by the Transport number. Or sometimes transports are sent at regular intervals. When this sorted list is transported to TEST/QA there are always some failures/errors which could be because the sort order isn’t right which is very possible because of many people working on the project and interdependencies between objects.
Then starts the exercise of reapplying some transports and creating new ones to fix earlier errors. This causes the sort order (and also the import times avaliable in STMS as it shows only the time of first import) to be thrown out the window. After a while order is restored in TEST/QA though and it works fine.
So what is the right sort criteria of transports you would say. From experience the right sort order of transports for PROD is the last date/time they were applied into TEST/QA. This makes sure that even if a transport was reapplied 5 times(let’s say) it is picked up only when it was last re-imported. We recently applied this order for our client’s go-live where we had to transport 600 change requests and it worked like a charm.
Cut to the chase now – Here’s the code.

All that is required is to input the User Ids that have worked on the project. This code can be tweaked to not look at specific user ids but apply to all transports that have made it to QA.

NOTE – Some minor changes will have to be made for each client –

1. The transport prefix might change from D01 to ER1 etc
2. The system abbreviations for Test and Prod might change from TST/PRD to QA/PROD etc.

*****************************************************************
REPORT  Z_CORRECT_CTS_ORDER.

TYPE-POOLS: ctslg.

DATA: gs_request  TYPE ctslg_request_info,
      gr_function LIKE RANGE OF gs_request-header-trfunction,
      gs_function LIKE LINE OF gr_function,
      BEGIN OF gs_trkorr,
        trkorr  TYPE e070-trkorr,
        as4user TYPE e070-as4user,
        as4text TYPE e07t-as4text,
      END OF gs_trkorr,
      gt_trkorr   LIKE TABLE OF gs_trkorr,
      BEGIN OF gs_transport,
        trkorr  LIKE e070-trkorr,
        as4user LIKE e070-as4user,
        as4text LIKE e07t-as4text,
        date    LIKE tstrfcofil-trdate,
        time    LIKE tstrfcofil-trtime,
      END OF gs_transport,
      gt_transports LIKE TABLE OF gs_transport,
      gs_system     LIKE LINE OF gs_request-cofile-systems,
      gs_step       LIKE LINE OF gs_system-steps,
      gs_action     LIKE LINE OF gs_step-actions.

SELECT-OPTIONS: s_user FOR  gs_request-header-as4user OBLIGATORY.
*PARAMETERS:     p_date LIKE gs_request-header-as4date OBLIGATORY.

INITIALIZATION.

  gs_function-sign = ‘I’.
  gs_function-option = ‘EQ’.
  gs_function-low = ‘K’. “Workbench Request
  APPEND gs_function TO gr_function.
  gs_function-low = ‘W’. “Customizing Request
  APPEND gs_function TO gr_function.

START-OF-SELECTION.

*– Get all released transports for the selected users
  SELECT a~trkorr a~as4user b~as4text INTO TABLE gt_trkorr
         FROM e070 AS a
         INNER JOIN e07t AS b
         ON a~trkorr EQ b~trkorr
         WHERE a~trkorr     LIKE ‘D01%’
         AND   a~trfunction IN gr_function
         AND   a~trstatus   EQ ‘R’ “Released
         AND   a~as4user    IN s_user
         AND   b~langu      EQ sy-langu.

  CHECK gt_trkorr IS NOT INITIAL.
  CLEAR gt_transports.
  LOOP AT gt_trkorr INTO gs_trkorr.
*– Read the info including transport logs of this request
    CALL FUNCTION ‘TR_READ_GLOBAL_INFO_OF_REQUEST’
      EXPORTING
        iv_trkorr = gs_trkorr-trkorr
      IMPORTING
        es_cofile = gs_request-cofile.
*– Check if this request ahs already made it to PROD and if
*– it has ignore it
    READ TABLE gs_request-cofile-systems INTO gs_system WITH KEY systemid = ‘PRD’.

    IF  sy-subrc IS INITIAL
    AND LINES( gs_system-steps ) GT 1.
      CONTINUE.
    ENDIF.

*– Check if this transport has made it to TEST and include it
*– in the list only if it sits in TEST
    READ TABLE gs_request-cofile-systems INTO gs_system WITH KEY systemid = ‘TST’.

    CHECK sy-subrc IS INITIAL
    AND   LINES( gs_system-steps ) GT 1.

    LOOP AT gs_system-steps INTO gs_step.
      LOOP AT gs_step-actions INTO gs_action.
      ENDLOOP.
    ENDLOOP.

*– Add the last date and time it was transported to TEST
    MOVE-CORRESPONDING: gs_trkorr  TO gs_transport,
                        gs_action  TO gs_transport.

    APPEND gs_transport TO gt_transports.

  ENDLOOP.

  IF gt_transports IS INITIAL.
    EXIT.
  ENDIF.

  SORT gt_transports BY date time.

END-OF-SELECTION.

  PERFORM output_data.

*&———————————————————————*
*&      Form  OUTPUT_DATA
*&———————————————————————*
*       text
*———————————————————————-*
*  –>  p1        text
*  <–  p2        text
*———————————————————————-*
FORM output_data .

  DATA:
    lcl_table   TYPE REF TO cl_salv_table,
    lcl_cols    TYPE REF TO cl_salv_columns_table,
    lcl_funcs   TYPE REF TO cl_salv_functions_list,
    lcl_display TYPE REF TO cl_salv_display_settings.

  TRY.
      CALL METHOD cl_salv_table=>factory
        EXPORTING
          list_display = if_salv_c_bool_sap=>false
        IMPORTING
          r_salv_table = lcl_table
        CHANGING
          t_table      = gt_transports.
    CATCH cx_salv_msg .
  ENDTRY.

  lcl_cols = lcl_table->get_columns( ).
  lcl_cols->set_optimize( if_salv_c_bool_sap=>true ).

  lcl_funcs = lcl_table->get_functions( ).
  lcl_funcs->set_all( ).

  lcl_display = lcl_table->get_display_settings( ).
  lcl_display->set_striped_pattern( if_salv_c_bool_sap=>true ).

  lcl_table->display( ).

ENDFORM.                    ” OUTPUT_DATA

To report this post you need to login first.

7 Comments

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

  1. Dave Grundy
    Salil,

    been there, done that. I’ve spent too many late nights at the weekend trying to get the transport sequence right, and arguing with the Basis team (who, in my experience, are usually very unhappy about re-importing). Also, if a system upstream of Development is restored to an earlier date, the usual rebuild is to re-import all transports from that date. So, regardless of the pain and inconvenience, in my view the best and safest method is to raise additional corrective transports. Then that sequence is entirely repeatable with no manual intervention when moving to Production. Unless, of course, the import of a transport proves catastrophic, but that’s a different story…

    Cheers,
    David

    (0) 
    1. Salil Mehta Post author
      Hi David

      Absolutely agree with you about raising corrective transports. That would always be the first step to solve a transport error. These situations vary from project to project and we’ve had cases where after applying a corrective transport we’ve found that even that has errors as there is a third transport lurking somewhere which has ruined the party. And in our case where there was more than 600 transports(and getting approval to get another one transported needed a lot of to-ing and fro-ing) re-applying a transport that we knew would fix the cause seemed a pretty good option. And that’s where the report above helps.

      Regards
      Salil

      (0) 
  2. B. Meijs
    Hi,

    Good post and very useful program. But using transport log information has one major drawback: it only works if the transport log is up to date (and available). What happens if a system copy is made from for example production to the quality system, or the quality system is replaced by another system. And what happens if the transport log is deleted.

    Have you considered reading the transport data from the E070 table? In a target system, it contains a date/time stamp of the moment a transport was imported. This way, you’ll always get up-to-date information.

    Ben

    (0) 
    1. Salil Mehta Post author
      Hi Ben

      Thanks for that. In fact the program does use E070 to obtain the transport data (it’s just been called transport log in the blog).

      Regards
      Salil

      (0) 
  3. Jens Schwarz
    Thanks for the goog and helpful work.

    I modified the report in that way, that it only shows transport requests that are not deleted from the import queue of the prod system.

    * Show requests that are removed from import queue?
      IF p_delq = ‘X’.
        CLEAR ls_settings.
      ELSE.
        ls_settings-detailed_depiction = ‘X’.
      ENDIF.

      LOOP AT gt_trkorr INTO gs_trkorr.
    *– Read the info including transport logs of this request
        CALL FUNCTION ‘TR_READ_GLOBAL_INFO_OF_REQUEST’
          EXPORTING
            iv_trkorr   = gs_trkorr-trkorr
            is_settings = ls_settings
          IMPORTING
            es_cofile   = gs_request-cofile.
    *– Check if this request ahs already made it to PROD and if
    *– it has ignore it
        LOOP AT gs_request-cofile-systems
           INTO gs_system
           WHERE systemid = ‘P8A’.
          EXIT.
        ENDLOOP.

    Regards
    Jens

    (0) 
  4. Jens Schwarz
    Thanks for the good and helpful work.

    I modified the report in that way, that it only shows transport requests that are not deleted from the import queue of the prod system.

    * Show requests that are removed from import queue?
      IF p_delq = ‘X’.
        CLEAR ls_settings.
      ELSE.
        ls_settings-detailed_depiction = ‘X’.
      ENDIF.

      LOOP AT gt_trkorr INTO gs_trkorr.
    *– Read the info including transport logs of this request
        CALL FUNCTION ‘TR_READ_GLOBAL_INFO_OF_REQUEST’
          EXPORTING
            iv_trkorr   = gs_trkorr-trkorr
            is_settings = ls_settings
          IMPORTING
            es_cofile   = gs_request-cofile.
    *– Check if this request ahs already made it to PROD and if
    *– it has ignore it
        LOOP AT gs_request-cofile-systems
           INTO gs_system
           WHERE systemid = ‘P8A’.
          EXIT.
        ENDLOOP.

    Regards
    Jens

    (0) 

Leave a Reply