TMS Auftragsmonitor Ausgabe

Transport Management System: TMS Auftragsmonitor

Die Übersicht über SAP Transportaufträge im Transport Management System zu behalten, ist ohne ChaRM nicht einfach. In welche Systeme, welche Aufträge importiert sind, wird häufig manuell und fehleranfällig über eine Schattenbuchhaltung in Excel realisiert. In diesem Beitrag implementieren wir einen TMS Auftragsmonitor, der uns die Übersicht über die Importe liefert. Damit wird kein Auftrag mehr irgendwo vergessen. Dies ist der 2. Teil unserer TMS Helpertools, nachdem wir im 1. Teil einen Transport von Kopien Erzeuger implementiert haben.

Benutzung des TMS Auftragsmonitor

Beim Start des Programms ZBC_TMS_REQUEST_MONITOR öffnet sich der Selection Screen. Über das Start- und Endedatum wählst Du den zu analysierenden Zeitraum aus. Das Programm analysiert alle in diesem Zeitraum freigegebenen Aufträge. Optional kannst Du die Selektion auf ein oder mehrere Transportaufträge weiter einschränken.

TMS Auftragsmonitor Selektion

Das Programm selektiert die Aufträge und ermittelt aus der TMS Konfiguration die beteiligten Systeme (Test, PreProd, Produktion…). Für jedes gefundene System liest das Programm per Remote Function Call die Import Historie.

Die Ausgabe des Programms ist ein ALV Grid, in dem eine einzelne Zeile den Importstatus des Auftrags in den beteiligten Systemen anzeigt. Auf der Abbildung sieht man, dass die Systemlandschaft in diesem Fall aus dem Testsystem CC2, einem weiteren Testsystem CC7, dem PreProd System PL2 und dem Produktivsystem PC2 besteht. Für jedes System ist der Import Returncode sowie der Importzeitpunkt sichtbar. Die Erzeugung der Grid Spalten erfolgt dynamisch, da die SAP Systemlandschaft bei Dir sicherlich anders aussieht.

TMS Auftragsmonitor Ausgabe

In unserem Beispiel ist noch kein Auftrag in CC7 importiert. Der Auftrag EC2K915770 ist in alle Systeme bis zur Produktion PC2 importiert. Der Auftrag EC2K915837 ist nur in das CC2 importiert. Die Importe in die Folgesysteme sind noch ausstehend. Im Grid siehst Du ausstehende Importe daran, dass die Zellen leer sind.

Über Hyperlinks im Grid kann zum einen zum Transportauftrag und zum anderen zum Transportprotokoll navigiert werden. Die Abbildung zeigt den Aufrag EC2K915837. Gut zu sehen ist, dass er für den Import in PC2 und PL2 vorgemerkt ist und in CC2 bereits importiert wurde. Dies ist also ein Auftrag, der das Produktivsystem noch nicht erreicht hat und im Status Test ist.

Transportprotokoll

TMS Import Historie

Die Importhistorie ist im SAPGUI in Transaktion STMS nach Auswahl des Systems und Wählen des Menüpunkt Springen\Import Historie zugreifbar. Das Programm kann also aus dem Entwicklungssystem heraus ermitteln, wo die Aufträge bereits importiert wurden. Deshalb ist dieses Programm vollständig funktionsfähig, wenn Du es in Deinem Entwicklungssystem implementierst.

Importhistorie

Implementierung

Den Code kannst Du hier herunterladen. Das Programm ZBC_TMS_REQUEST_MONITOR besteht aus den folgenden Teilen

  • Klasse LCL_UI_CTR: UI Logik zur Darstellung der Infos im Grid
  • Klasse LCL_TMS_CTR: Auswertung der Aufträge und Import Historien
  • Interface LIF_CONST: Typen und Konstanten, welche durch UI- und TMS-Controller benutzt werden
  • Klasse LCL_TEST: Unit Test Klasse für den TMS-Controller
  • Klasse LCX_T100: Ausnahmeklasse, welche eine T100-Nachricht kapselt

TMS Auftragsmonitor Implementierung

Implementierung Importhistorie auswerten

Die Logik zur Auswertung der Import Historie steckt zum größten Teil in der Methode lcl_tms_ctr, query_request. Die Aufträge werden aus den Tabellen e070 und e07t selektiert. Die Importhistorie für einen Zeitraum und einem SAP System geschieht über Funktionsbaustein TMS_TM_GET_HISTORY. Intern nutzt der Baustein RFCs, um via den RFC-Destinationen TMSADM* die Informationen aus den Systemen zu ermitteln. Das ist übrigens unter dem Sicherheitsaspekt kein Problem, da der verwendete Systembenutzer TMSADM im Mandanten 000 nur die relevanten TMS-Funktionsbausteine aufrufen kann und sonst nichts.

  METHOD query_request.
    DATA lt_request TYPE lif_const=>tt_request.
    DATA lt_sysnam TYPE lif_const=>tt_synam.
    DATA lv_domnam TYPE tmsdomnam.
    FIELD-SYMBOLS <lv_sysnam> TYPE tmssysnam.
    DATA lv_start_date TYPE d.
    DATA lv_start_time TYPE t VALUE '000000'.
    DATA lv_end_date TYPE d.
    DATA lv_end_time TYPE t VALUE '235959'.
    DATA lt_alog TYPE tmstpalogs.
    DATA ls_alert TYPE stmscalert.

    REFRESH et_request_mon.

*   Aufträge gemäß Selektion selektieren
    SELECT
      e070~trkorr
      e070~trfunction
      e070~as4date
      e070~as4time
      e07t~as4text
     FROM e070 LEFT OUTER JOIN e07t ON
      e070~trkorr = e07t~trkorr
*     Keine Selektion über e07t~langu, weil es unterschiedliche
*     Sprachen sein können
     INTO TABLE lt_request WHERE
        e070~trfunction IN (lif_const=>gc_enum_trfunction-workbench_request, lif_const=>gc_enum_trfunction-customizing_request) AND
        e070~trstatus = lif_const=>gc_enum_trstatus-released AND
        e070~trkorr IN it_rng_trkorr AND
        e070~as4date BETWEEN iv_start_date AND iv_end_date.

    IF sy-subrc <> 0.
      lcx_t100=>raise_exc_by_msg( |Keine freigegebenen Cust/Wrkb-Aufträge in Zeitraum gefunden| ).
    ENDIF.

*   Aus der TMS Konfiguration die beteiligten System sowie die Domäne ermitteln
    read_tms_config(
      IMPORTING
        et_sysnam = lt_sysnam
        ev_domnam = lv_domnam ).

    lv_start_date = iv_start_date.
    lv_end_date = iv_end_date.

*   Für jeden System die Importhistorie ermitteln
    LOOP AT lt_sysnam ASSIGNING <lv_sysnam>.

      CALL FUNCTION 'TMS_TM_GET_HISTORY'
        EXPORTING
          iv_system     = <lv_sysnam>
          iv_domain     = lv_domnam
        IMPORTING
          et_tmstpalog  = lt_alog
          es_exception  = ls_alert
        CHANGING
          cv_start_date = lv_start_date
          cv_start_time = lv_start_time
          cv_end_date   = lv_end_date
          cv_end_time   = lv_end_time
        EXCEPTIONS
          alert         = 1
          OTHERS        = 2.

      IF sy-subrc <> 0.
*       Adaptiert aus FuBa TMW_TM_GET_HISTORY.
*       Nachricht TP 702: Keine Protokolleinträge im selektierten Bereich
        IF ( lt_alog IS INITIAL AND
           ls_alert-msgid = 'TP' AND
           ls_alert-msgno = '702' ) OR
           ls_alert-error <> 'OK'. "Fehler bei Zugriff auf das System

*         System ignorieren
          CONTINUE.
        ELSE.
          lcx_t100=>raise_exc_by_sy( ).
        ENDIF.
      ENDIF.

*     Sortierung des alogs wegen Binary Search in Methode fill_request_mon
      SORT lt_alog BY trkorr.

*     Ausgabetabelle in Parameter et_request_mon füllen
      fill_request_mon(
        EXPORTING
          iv_sysnam = <lv_sysnam>
          it_request = lt_request
          it_alog = lt_alog
        CHANGING
          ct_request_mon = et_request_mon ).

    ENDLOOP.
  ENDMETHOD.

Die Methode fill_request_mon bereitet die Infos aus der Importhistorie auf. Der folgende Debugger Screenshot zeigt die in dieser Methode aufgebaute Datenstruktur.

TMS Auftragsmonitor Interne Datenstruktur

Implementierung UI Grid aufbauen

Die Implementierung des UI Controllers ist nicht ganz so einfach, weil die Datenstruktur für das Grid nicht statisch definierbar ist. Für jedes SAP System der Transportdomäne werden 2 Spalten für Returncode und Importzeitpunkt benötigt. Der Code nutzt deshalb exzessiv dynamische Programmierung zur Erzeugung von Datentypen -objekten (Klassen cl_abap_structdescr etc., ABAP-Kommando CREATE DATA). Die folgende Methode  lcl_ui_ctr, init_ui_data_structure zeigt exemplarisch den dynamischen Aufbau der UI Struktur für das ALV Grid. Ergebnis der Methode ist eine Referenz auf eine interne Tabelle, welche die Felder passend zur SAP Systeminfrastruktur enthält.

  METHOD init_ui_data_structure.
    DATA lr_tabledescr TYPE REF TO cl_abap_tabledescr.
    DATA lr_structdescr TYPE REF TO cl_abap_structdescr.
    DATA lt_comp TYPE abap_component_tab.
    DATA ls_comp TYPE abap_componentdescr.

*   Jedes Feld aus Type lif_const=>ts_request aufnehmen
    ls_comp-name = 'TRKORR'.
    ls_comp-type ?= cl_abap_elemdescr=>describe_by_name( 'TRKORR' ).
    APPEND ls_comp TO lt_comp.

    ls_comp-name = 'TRFUNCTION'.
    ls_comp-type ?= cl_abap_elemdescr=>describe_by_name( 'TRFUNCTION' ).
    APPEND ls_comp TO lt_comp.

    ls_comp-name = 'AS4DATE'.
    ls_comp-type ?= cl_abap_elemdescr=>describe_by_name( 'AS4DATE' ).
    APPEND ls_comp TO lt_comp.

    ls_comp-name = 'AS4TIME'.
    ls_comp-type ?= cl_abap_elemdescr=>describe_by_name( 'AS4TIME' ).
    APPEND ls_comp TO lt_comp.

    ls_comp-name = 'AS4TEXT'.
    ls_comp-type ?= cl_abap_elemdescr=>describe_by_name( 'AS4TEXT' ).
    APPEND ls_comp TO lt_comp.

*   Jetzt für jedes System die Infos aus lif_const=>ts_request_imp aufnehmen
    LOOP AT it_sysnam ASSIGNING FIELD-SYMBOL().
      ls_comp-name = get_fieldname(
          iv_fieldname = 'RETCODE'
          iv_sysnam    =  ).
      ls_comp-type ?= cl_abap_elemdescr=>describe_by_name( 'TRRETCODE' ).
      APPEND ls_comp TO lt_comp.

      ls_comp-name = get_fieldname(
          iv_fieldname = 'TRTIME'
          iv_sysnam    =  ).
      ls_comp-type ?= cl_abap_elemdescr=>describe_by_name( 'TSTAMP' ).
      APPEND ls_comp TO lt_comp.

    ENDLOOP.

    lr_structdescr = cl_abap_structdescr=>create(
        p_components = lt_comp ).

    lr_tabledescr = cl_abap_tabledescr=>create(
        p_line_type  = lr_structdescr ).

    CREATE DATA rr_request_mon_ui TYPE HANDLE lr_tabledescr.

  ENDMETHOD.

Die folgende Abbildung aus dem Debugger zeigt die gefüllte interne Tabelle, mit welcher das Grid befüllt wird.

TMS Auftragsmonitor UI Struktur

Fazit

Der TMS Auftragsmonitor liefert eine gute Übersicht, in welche Zielsysteme freigegebene Transportaufträge noch zu transportieren sind. Er ist ein Workaround, wenn kein ChaRM eingesetzt wird. In unseren Projekten finden wir jedoch häufig diese Situation vor und müssen entsprechend damit umgehen. Von der Implementierung her zeigt er, wie man in ABAP gegen dynamische Datenstrukturen programmiert.

 

Hast du noch Fragen?
Nutze gerne unsere Kommentarfunktion!

 

Du programmierst, bist ABAP-interessiert und hast Lust coole Projekte mit uns zu machen? Wir suchen dich! Schau doch mal in unserer Stellenbeschreibung vorbei.

Über den Autor

Rüdiger Lühr

Kommentieren

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

1 + 3 =