ChaRM Hilfsfunktionen API

Wer als ABAP Entwickler im Umfeld SAP Solution Manager Change Request Management unterwegs ist, wird sehr häufig auf grundlegende Funktionalitäten der Vorgangsbearbeitung oder des Transportwesens zugreifen wollen. Sehr häufig finden sich entsprechende Methoden in folgenden ABAP-OO-Klassen. Eigentlich kennt die jeder ChaRM-Entwickler, aber manchmal überlege auch ich: „Wie hieß die Klasse nochmal?“.

Hier mein Spickzettel:

  • CL_HF_HELPER
  • CL_AL_CRM_CM_UTILITY
  • /TMWFLOW/CL_TRANSPORT_UTIL

Neu seit Solution Manager 7.2:

  • CL_AIC_CM_SCOPE_BACKEND_API
  • CL_AIC_CM_TRANS_BACKEND_API
  • CL_AIC_TWB_CONT_BACKEND_API

Und zum nachschauen, wie es der SAP-Standard tut:

  • Proxy-Klassen: CL_CHM1_INSTANCE (und verwandte Klassen CL*CHM1*INSTANCE*), hier speziell Methoden IF_EX_SOCM_PROCESS_ACTION~PROCESS_ACTION und IF_EX_SOCM_CHECK_CONDITION~CHECK_CONDITION
  • Kopiersteuerung: CL_IM_AI_CRM_COPY_BADI
  • BOL/GenIL: CL*AI*RUN_BTIL (z.B. Transportverwaltung, Landschaftsverwaltung etc.)

Die wichtigste Tabelle ist und bleibt für immer und ewig [bis 2025 😉 ] CRMD_ORDERADM_H.

SAP Solution Manager 7.2 ChaRM Upgrade mit Erhalt und Weiterverwendung der Änderungsprozesse aus SAP Solution Manager 7.0

Frage: Gibt es die Möglichkeit, einen Upgrade von SAP Solution Manager 7.0 (SAP GUI) nach SAP Solution Manager 7.2 (Web UI) durchzuführen und hierbei die kundeneigenen Änderungsprozesse zu erhalten und weiterzuverwenden?

Antwort 1: Laut offizieller Aussage der SAP SE gibt es keinen Migrationspfad. Das heißt, es müssen neue Änderungsvorgänge konfiguriert werden, wobei einige Teile wiederverwendet werden können. Hierzu gibt es von SAP SE bereitgestellte Leitfäden für den Upgrade SM 7.0 nach 7.1 und für den Upgrade SM 7.1 nach 7.2.

Antwort 2: Nach meiner Erfahrung aus konkreten Projekteinsätzen ist es möglich. Da diese Form des Upgrades von SAP SE nicht vorgesehen ist, sind jedoch einige manuelle Konfigurations- und Entwicklungsaktivitäten durchzuführen. Der Upgradeaufwand liegt je nach Komplexität der Kundenlösung bei ca. 18 PT.

Die wichtigsten Aktivitäten im Überblick:

  • Customizing migrieren (SAP GUI -> Web UI, z.B. Proxyklassen)
  • Customizing migrieren (alte Tabellen -> neue Tabellen, z.B. Kopiersteuerung, PPF-Aktionen -> Drucktasten in Landschafts- und Transportverwaltung)
  • Customizing für neue Funktionalitäten ausprägen (z.B. Transportrisiko, Downgrade-Protection)
  • SAP Web Client UI konfigurieren
  • Sachverhalt + IBase-Komponente mittels Entwicklung im Änderungsantrag bereitstellen
  • Kontext (direkte Projektzuordnung) mittels Entwicklung einmalig nachgenerieren
  • Optional: Kontext (direkte Projektzuordnung + Umfang) anhand Sachverhalt und IBase-Komponente im Änderungsantrag mittels Entwicklung automatisch finden
  • Optional: Kundeneigene Entwicklungen migrieren (z.B. Wertehilfen für kundeneigene Felder)

Ich habe u.a. ein Upgrade SM 7.0 -> SM 7.1 im Jahr 2013 und ein Upgrade SM 7.0 -> SM 7.2 im Jahr 2018 durchgeführt und kann hierdurch bezeugen: Es funktioniert wirklich.

Bei Fragen zu den Details kommen Sie gern auf mich zu. Wenn Sie Unterstützung bei Ihrem Upgrade benötigen, dann melden Sie sich bitte bei mir. Ich helfe Ihnen gern.

PS: Seit dem Upgrade auf SAP Solution Manager 7.2 sind die alten Änderungsvorgänge aus dem SAP Solution Manager 7.0 im SAP Web Client UI nicht mehr auffindbar. Eine nachträgliche Mini-Migration SM 7.0 -> SM 7.2 für abgeschlossene Vorgänge ist möglich. Aufwand: ca. 5 PT.

Filterung der Systeme in „Create Transport Request“ Popup abhängig von Berechtigungen und bereits angelegten Transporten

Hintergrund:

Beim Anlegen von Transportaufträgen stehen alle zum Projekt gehörenden Entwicklungssysteme zur Auswahl. Eine Einschränkung erfolgt nicht. Durch Ausprägung der Beispielimplementierung AIC_ONLY_DEV_IBASE_SYSTEM des BADIs AIC_CREATE_TRANSPORT_WINDOW kann eine Einschränkung gemäß IBase-Komponente aktiviert werden.

Problem:

Das hilft uns nicht weiter, da die Transportwege wie folgt sind:

  • EXX.900 -> PXX.900
  • EXX.100 -> PXX.100
  • EXX.910 -> PXX.900 + PXX.100

Es sind also zwei IBase-Komponenten auswählbar. Bei Auswahl von PXX.900 kann bei aktiver Beispielimplementierung im EXX.900 und EXX.910 implementiert werden. Bei Auswahl von PXX.100 kann in EXX.100 und EXX.910 implementiert werden. Es ist somit also nicht möglich die Implementierung ausschließlich in EXX.100 oder EXX.910 zu erzwingen.

Lösung:

  • Eigene BADI-Implementierung ZSM_AIC_CREATE_TRANSPORT_LIST.
  • Change Manager dürfen Transporte in allen Systemen anlegen. (Identifizierung anhand der Genehmigungs-Aktivität im Approval Management – SM_APP_AP)
  • Entwickler dürfen jedoch nur Transporte zu Entwicklungssystemen anlegen, in denen bereits Transporte angelegt wurden.
  • User dürfen generell Transporte in allen Systemen anlegen, wenn noch keine Transportaufträge angelegt und damit der Scope noch nicht festgelegt wurde.

Code-Schnipsel:

METHOD cl_aic_create_transport_window~filter_systems.

DATA:
lt_transp_req TYPE socmt_trordhc_type.

FIELD-SYMBOLS:
<fs_system_list> LIKE LINE OF ct_system_list.

*Valid parameters?
CHECK iv_header_guid IS NOT INITIAL AND ic_header_bol IS BOUND.

*If only one source system is available we want to keep it.
*Therefore all old unharmonized projects will run as before.
CHECK linesct_system_list 1.

*Check authority. (User has authority to approve a step in approval management?)
AUTHORITY-CHECK OBJECT 'SM_APP_AP'
*          ID 'AIC_PROC' FIELD lv_process_type
ID 'AIC_PROC' DUMMY
ID 'ACTVT' FIELD '37'.

*Authority given. Allow everything.
CHECK sy-subrc <> 0.

*Get all already created transport requests.
CALL METHOD /tmwflow/cl_transport=>get_chng_doc_transp_req
EXPORTING
iv_header_guid iv_header_guid
IMPORTING
et_transp_req  lt_transp_req.

*No transport created yet. Allow everything.
CHECK lt_transp_req IS NOT INITIAL.

*Check systems and delete all systems which are not already used.
LOOP AT ct_system_list ASSIGNING <fs_system_list>.
READ TABLE lt_transp_req TRANSPORTING NO FIELDS WITH KEY
trorder_system <fs_system_list>-sysname
trorder_client <fs_system_list>-client.
IF sy-subrc <> 0.
DELETE ct_system_list.
ENDIF.
ENDLOOP.

ENDMETHOD.

 

Welche Retrofit-ToCs können aus der Importqueue gelöscht werden?

SAP Note 2636996 – Retrofit Transport of Copies remains in Import Queue after performing Manual Retrofit

Extrakt aus dem SAP-Hinweis:

Cause

  • If you perform changes manually in the Retrofit System, then the Transport of Copies generated when releasing the Transport Request from ChaRM will stay in the Import Buffer
  • Performing changes manually in the Retrofit System in this manner is an exceptional situation, and in this case the ChaRM Retrofit scenario does not have a mechanism to delete the Transport of Copies from the Import Buffer of the Retrofit System
  • Transport of Copies deletion will not occur automatically when the Retrofit data is generated and then you decide to make the same changes (which were previously done in the Maintenance Development System) manually in the Retrofit System without using the ChaRM Retrofit Tool
  • This needs to be performed manually at TMS level

Resolution

For each Retrofit Transport of Copies currently remaining in the Import Buffer:

  1. Ensure that the associated changes are fully completed manually in the Retrofit System
  2. Manually remove the Transport of Copies from the Import Buffer using Transaction code STMS

Mein Kommentar dazu:

So ein Quatsch. Natürlich wäre es sinnvoll, die ungenutzten ToCs beim abschließen des Retrofits automatisch aus der Importqueue zu löschen.

Ergänzung zum SAP-Hinweis: Welche ToCs können aus der Importqueue gelöscht werden?

  1. (Ermittle Original-Transport ohne TOC-Status bzw. Import-Returncode aus Tabelle /TMWFLOW/TOCASNG.)
  2. Ermittle Originaltransporten aus Tabelle /TMWFLOW/RFITC gemäß vorheriger Selektion und welche den Retrofitstatus <> „“ [Retrofit bereits verarbeitet] und ggf. <> „D“ [Retrofit nicht automatisch verarbeitet] haben.
  3. Ermittle ToCs aus Tabelle /TMWFLOW/TOCASNG zu Originaltransporten aus vorheriger Selektion. Ermittle außerdem alle ToCs mit Status Inaktiv [Retrofitdaten wurden neu erzeugt].
  4. Die ermittelten ToCs können aus der Importqueue gelöscht werden, sofern noch nicht geschehen.

Genehmigungsprozess im Änderungsdokument für QA-Freigabe nutzen

Ausgangsituation:

Im Änderungsantrag gibt es Genehmigungsprozesse, um mehrstufige oder parallele Genehmigungen abbilden zu können. Im Änderungsdokument gibt es das nicht, wir benötigen das dort aber ebenfalls, um mehrstufige oder parallele Tests/QA-Freigaben abbilden zu können.

Lösung:

Wir stellen den Genehmigungsprozess auch für Änderungsdokumente bereit. Dies funktioniert ohne Entwicklungsaufwand für SAP Solution Manager 7.1 und 7.2. Aufwand: ca. 3 PT

Aktivitäten:

Im Folgenden werden die hierfür erforderlichen Konfigurationsschritte dokumentiert.

  1. Web UI:
    1. Feld Genehmigungsvorgang im Detailformular
    2. Zuordnungsblock Genehmigung in Übersichtsseite
    3. Suchkriterien auf Suchseite
    4. Felder im Änderungsprotokoll
  2. Genehmigungsprozess:
    1. Optional: Genehmigungspartner [i.R. Tester]
    2. Optional: Genehmigungstatusschema [i.R. SAP-Standard]
    3. Genehmigungsschritte (inkl. Vorgänger/Nachfolger)
    4. Genehmigungsvorgänge
    5. Genehmigungsfindungsschema
    6. Optional: Automatische Partnerfindung für Genehmigungsschritte
    7. Optional: Automatische Findung für Genehmigungsvorgang
  3. Statusfluss:
    1. Start der Genehmigung (C4AP) [i.R. Zu Testen]
    2. Statuswechsel bei erfolgreicher Genehmigung (CAAP) [i.R. Erfolgreich getestet]
    3. Statuswechsel bei Ablehnung [i.R. In Entwicklung]
    4. Optional: Statuswechsel bei „Nicht Relevant“
    5. PPF-Aktion für Statuswechsel (ZXXX_APPROVAL_PROCEDURE_STATUS)
    6. Prüfung, ob Genehmigungsvorgang und Partner für Schritte gewählt sind [i.R. Warnung: Angelegt + In Entwicklung; Abbruch: Zu Testen ChaRM-Konsistenzprüfung APPROVER_FILLED]
    7. Genehmigung wiederholen [i.R. in Entwicklung; ChaRM-Aktion APP_PROC_INI; ggf. als PPF-Aktion HF_EXECUTE_ACTION]
    8. Deaktivieren der alten PPF-Aktion zum Genehmigen/Testen mittels Aktion
  4. Workflow/Benachrichtigung:
    1. Automatisches Workflowcustmizing (SWU3)
    2. PPF-Aktion Workflowauslösung (ZXXX_IT_RFC_APPROVAL_WORKFLOW)
    3. Titel und Beschreibung für Workitem ändern (Texte der Aufgaben TS17107931 und TS17107930 in Transaktion PFTC überdefiniert; danach Puffer synchronisieren mittels TA SWU_OBUF)
    4. Workitems per Mail versenden (Report RSWUWFML2 als Job einplanen; User muss E-Mail-Adresse in SU01 haben.)
  5. Berechtigungen für Genehmigungen und Vertretungen:
    1. Berechtigungsobjekt CRM_APPRVL (Vorgang anlegen, Genehmigungsvorgang wählen, Schritte bearbeiten)
    2. Berechtigungsobjekt SM_APP_AP (Genehmigungsvorgang wählen, Schritte hinzufügen/löschen, Genehmigen für sich selbst, Genehmigen für andere)
    3. Berechtigungsobjekt B_BUPR_BZT (Hinzufügen/Löschen, BUR013: Pflegen eigene Vertreter)
    4. Berechtigungsobjekt B_BUPA_RLT (Anzeigen; Auswahl GP)
    5. Berechtigungsobjekt B_BUPA_RLT (Ändern, *: Pflegen Fremdvertretungen)
    6. Erweitertes Genehmigungsverfahren mit exakten Berechtigungen und Vertreterregelung (DNO_CUST04 -> ENH_APP)
    7. Optional: Keine Einschränkung der Vertreter auf eigene Orgeinheit (AGS_WORL_CUSTOM -> IM_BP_SEARCH_RESTRICT_DISABLE = X oder Berechtigungsobjekt SM_SDK_ACT mit SMSDACTION = „PROC“)
  6. Optimierungen (Modifikation/Erweiterung):
    1. Genehmigungsvorgang für Altvorgänge nachträglich auswählen (im SAP-Standard erfolgt Initialisierung des Approval-Sets beim Anlegen des Vorganges. Folglich können für bereits existierende Vorgänge keine Genehmigungsvorgänge gewählt werden. Die Prüfungen verhindern aber ein Weiterprozessieren ohne Genehmigung.) -> Modifikation in Methode CL_SRQM_RFC_REQUESTFORCH0_CN12->ON_NEW_FOCUS + Modifikation in FUBA CRM_APPROVAL_TRIGR_EC
    2. Beenden der Genehmigung sobald der erste Tester ablehnt (im SAP Standard müssen alle Genehmigungsschritte bearbeitet sein. Selbst wenn der erste Tester ablehnt, muss der zweite genehmigen/ablehnen. Einfluss auf das Ergebnis hat dies nicht.) -> Modifikation in FUBA AIC_SRQM_RFC_APPROVAL_STAT_EC

Das Textlog enthält viele unnütze technische Einträge. Die kann man ausblenden.

Hintergrund:

Zahlreiche Aktivitäten im ChaRM fügen Einträge im Textprotokoll hinzu. Nicht alle Einträge sind sinnvoll/hilfreich. Bei zu vielen Einträge leidet jedoch die Übersichtlichkeit.

Anforderung:

Ausblenden von ausgewählten Einträgen. Z.B. Erzeugen von ToCs.

Beispiele:

  • Leerer Auftrag DEVK908714 in Aufgabenplan M000000082 wurde gelöscht
  • Aktion Aufträge freigeben ohne offene Transportaufträge ausgeführt!
  • Aufträge werden gelöscht
  • Für die Aufträge DEVK908722 wurden Kopien DEVK908725 transportiert

Lösung 1:

Das Schreiben von Textprotokolleinträgen erfolgt mittels Methode „cl_hf_helper=>insert_notice“. Übergabeparameter ist die vollständige Textzeile.
Hier kann mittels Mustererkennung (z.B. regulärer Ausdruck) nach bestimmten Einträgen gesucht und das Schreiben unterbunden werden. Nachteil: Mustererkennung ist teilweise aufwendig und sprachabhängig.
Vorteil: Diese Lösung klappt für fast alle Einträge.

Lösung 2:

Das Schreiben von Textprotokolleinträgen erfolgt in den meisten Fällen mit „cl_chm1_instance->handle_message“ welche wiederum u.a. cl_hf_helper=>insert_notice ruft. Übergabeparameter sind hier Nachrichtenklasse, Nachrichtennummer und Nachrichtenparameter.
Hier kann somit die Filterung mittels Nachrichtenklasse/-nummer erfolgen. Nachteil: Funktioniert nicht für Fälle in denen cl_hf_helper=>insert_notice direkt benutzt wird (z.B. Statuswechsel, Protokollierungen des Aufgabenplans). Vorteil: Sehr einfach und sprachunabhängig.

Lösung 3:

Für transportbasierte ChaRM-Aktionen (z.B. Transportauftrag anlegen, freigeben, …) aus dem Transportverwaltung-Zuordnungsblock wird Methode CL_AI_CRM_ACTION_UTILITY->HANDLE_ACTION_LOG verwendet um Nachrichten ins Textlog zu schreiben. Der Text wird hier abhängig vom Aktionsnamen dem Customizing TSOCM_ACT_DEF entnommen. Sind hier keine Nachrichten für die betreffende Aktion gepflegt, wird keine Nachricht geschrieben. Folglich können Nachrichten durch entsprechendes Customizing ausgeblendet oder geändert werden. Beispieltext: „Aufträge DEVK908729 angelegt“

Lösung 4:

In der Regel lösen alle Aktionen des Aufgabenplanes eine Protokollierung im Textlog aus. Um hier Nachrichten auszufiltern oder zu ändern, ist Funktionsbaustein /TMWFLOW/APPL_STAT_MESSAGE am Ende zu erweitern. Es ist hierbei zu beachten, dass Nachrichtenklasse und –nummer der Pseudo-Konsistenzbedingung 0POSITIVE_FEEDBACK oder 0NEGATIVE_FEEDBACK aus Tabelle TSOCM_COND_DEF entnommen werden und für alle Aktionen gleich sind. Hier muss also eine Einbeziehung des Aktionsnamens (L_ACTION_MESSAGE-TASK_ID) sowie ggf. weiterer Parameter erfolgen, um eine sinnvolle Filterung zu ermöglichen. Funktionsbaustein /TMWFLOW/APPL_STAT_MESSAGE wird von Methode CL_AI_CRM_ACTION_UTILITY-> HANDLE_ACTION_LOG für Aktionen des Tansportmanagement-ABs und von Methode IF_EX_SOCM_PROCESS_ACTION~PROCESS_ACTION der ChaRM-Proxy-Klassen für ChaRM-Aktionen mit Aufgabenplaninteraktionen gerufen. Methode IF_EX_SOCM_PROCESS_ACTION~PROCESS_ACTION nutzt wiederum cl_chm1_instance->handle_message aus Lösung 2. Beispieltext: „Die Aktion Transportauftrag anlegen in System DEV 100 des Typs Ausgangssysteme ist erfolgreich abgeschlossen.“

Lösung 5:

Es gibt noch einzelne weitere Stellen, die eine Protokollierung im Textlog vornehmen. Beispielhaft sei auf CL_AIC_CM_S_SYSTEMLANDSCA_IMPL->LOGON_SYSTEM beim Anmelden am System verwiesen. Ein Eingriff ist hier in der Regel nur mittels spezifischer Modifikation möglich. Beispieltext: „Systemanmeldungsprotokoll. Zielsystem: DEV 100“

Vorschlag A: Lösung 2 mit selbstpflegender Customizingtabelle

  • Aufwand: 4h
  • Customizingtabelle mit Pflegedialog (Klasse, Type, Nummer, Parameter 1-4, Text, Flag [Aktiv, Inaktiv, Unbestimmt])
  • Enhancement in cl_chm1_instance->handle_message am Anfang
  • Algorithmus zum automatischen Befüllen mit bisher unbekannten Nachrichten
  • Logik zum ausblenden/ausfiltern von Nachrichten gemäß Customizingtabelle
  • Test

Vorschlag B: Zusätzlich Lösung 4 implementieren 

  • Aufwand 1h (zusätzlich)
  • Customizingtabelle um Feld TASK_ID ergänzen
  • Lösung aus cl_chm1_instance->handle_message in leicht abgewandelter Form auch am Ende von FUBA /TMWFLOW/APPL_STAT_MESSAGE implementieren.

Code-Schnipsel:

METHOD CL_CHM1_INSTANCE->HANDLE_MESSAGE .

ENHANCEMENT 1  ZSM_TEXT_LOG_FILTER.    "active version

DATA:
ls_tlf TYPE ZSM_TLF.

*Build message text.
MESSAGE ID im_message-msgid
TYPE     im_message-msgty
NUMBER   im_message-msgno

INTO     me->msg_text

WITH     im_message-msgv1
im_message-msgv2
im_message-msgv3
im_message-msgv4.

*Get customizing entry.
*We are not looking at message parameters actually...maybe in future.
SELECT SINGLE *
INTO ls_tlf
FROM ZSM_TLF
WHERE MSGID = im_message-msgid AND
MSGNO = im_message-msgno AND
MSGTY = im_message-msgty.

*Create customizing entry if not existing yet.
IF sy-subrc <> 0.
ls_tlf-MSGID = im_message-msgid.
ls_tlf-MSGNO = im_message-msgno.
ls_tlf-MSGTY = im_message-msgty.
ls_tlf-ACTIVE_FLAG = ''.
ls_tlf-MSGV1 = im_message-msgv1.
ls_tlf-MSGV2 = im_message-msgv2.
ls_tlf-MSGV3 = im_message-msgv3.
ls_tlf-MSGV4 = im_message-msgv4.
ls_tlf-langu = sy-langu.
ls_tlf-MSGTX = me->msg_text.
INSERT INTO ZSM_TLF values ls_tlf.
ENDIF.

*Check whether message should be filtered out.
IF ls_tlf-active_flag = '-'.

*   write message into ppf-log
CALL METHOD cl_log_ppf=>add_message
EXPORTING
ip_problemclass = '4'
ip_handle       = im_appl_log.

*  Exit routine without writing message to text log.
RETURN.

ENDIF.

ENDENHANCEMENT.

MESSAGE ID     im_message-msgid
TYPE   im_message-msgty
NUMBER im_message-msgno

INTO me->msg_text

WITH   im_message-msgv1
im_message-msgv2
im_message-msgv3
im_message-msgv4.

*   write message into ppf-log
CALL METHOD cl_log_ppf=>add_message
EXPORTING
ip_problemclass = '4'
ip_handle       = im_appl_log.

DATA  l_text255 TYPE char255.
l_text255 = me->msg_text.
*   write message into action-log (text in change document)
CALL METHOD cl_hf_helper=>insert_notice
EXPORTING
im_text = l_text255
im_guid = me->if_socm_instance_attributes~change_document_id.

ENDMETHOD.

SAP Best Practice: SAP System Landscape Copy for SAP NetWeaver and SAP Solutions with additional steps for ChaRM or QGM

885343 – SAP System Landscape Copy

Please note that in SAP Solution Manager 7.1 you can use the Transport Monitor (transaction /TMWFLOW/TRMO) to detect the transport delta (transport requests which are imported to QAS but not imported to PRD). In SAP Solution Manager 7.2 you have to use the Administration Cockpit instead.

Quality Gate Management Szenario löschen

Frage: Lassen sich testweise angelegte Szenarien im Quality Gate Management (QGM) löschen?

Antwort: Vielleicht mit Tendenz zu Nein.


Change-Control-Landschaft anlegen, ändern und löschen:

https://help.sap.com/viewer/60943adf3ff44893b62c568bb8a87d17/7.2.05/de-DE/bba95557e03f9067e10000000a4450e5.html

Lösung löschen:

https://launchpad.support.sap.com/#/notes/2375895

Szenario schließen:

https://help.sap.com/viewer/8b923a2175be4939816f0981b73856c7/7.2.05/de-DE/92fa205a04594b089c4c51cf1afdafa1.html

Szenario anlegen und ändern:

https://help.sap.com/viewer/8b923a2175be4939816f0981b73856c7/7.2.05/de-DE/ba41da6d057f42cbae01d64926763007.html

Laut meinem Kenntnisstand lassen sich Szenarien nicht löschen. Das ist so ähnlich wie wenn sie Änderungszyklen und Aufgabenpläne im Change Request Management löschen wollten.

Offiziell geht das nicht. Bei Änderungszyklen gibt es einen Trick u.a. mittels Transaktion CRMD_ORDER oder Report CRM_ORDER_DELETE. Falls Szenarien auch nur CRM-Vorgänge sind, wäre das einen Versuch wert.

Möglich ist auch, dass das Szenario automatisch gelöscht wird, wenn die ganze Change-Control-Landschaft gelöscht wird.

Das wäre also auch einen Versuch wert, falls Sie die Change-Control-Landschaft nicht noch für was anderes nutzen.

Und wenn alle Stricke reißen: Dann verwenden Sie das Szenario doch einfach wieder, indem Sie die Szenariodaten ändern.

Ansonsten bleibt Ihnen nur das Abschließen. Oder Das Hoffen auf ein entsprechendes Feature in einem zukünftigen SP.

Prüfung kritischer Objekte / Critical Objects Check – Performanceoptimierung

Manchmal zweifle ich.

Nutzt überhaupt irgend jemand den SAP Solution Manager?

Gerade habe ich die Funktion „Prüfung kritischer Objekte / Critical Objects Check“ für 50.000 Objektdefinitionen getestet. Die Laufzeit von mehr als 10 Minuten für das Anlegen von Transportaufträgen, den Wechsel auf den AB „Transport Management“, das Erzeugen von ToCs oder die Freigabe von Transportaufträgen ist definitiv zu lang.

Wir alle wissen ja spätestens seit Einführung der Downgrade Protection (DGP), dass SAP SE gar nicht oder nur unter unrealistischen Laborbedingungen testet. Also hat auch hier SAP SE höchstens zwei bis drei kritische Objekte definiert und war dann mit der Performance sehr zufrieden.

Aber es muss doch da draußen auch Nutzer geben, die 10, 20, 100 oder sogar (wie wir) mehrere tausend kritische Objekte definieren?!

Zumal das Problem seit Einführung von Standard Changes im SAP Solution Manager 7.2 SP5 noch größer geworden ist, schließlich werden viele Anwender diese Änderungsart inklusive Whitelist-Feature nutzen wollen. Aber wenn da die Performance genauso ist, sehe ich schwarz.

Die schlechte Nachricht: SAP HANA hilft hier nicht viel. Das ist einfach nur richtig schlechte Programmierung.

Die gute Nachricht: Das Problem ist durch lokale Optimierungen lösbar:

Es kann so einfach sein.

Funktionsbaustein /TMWFLOW/RCK_CHECK_SM_CALL wird für die Durchführung der Prüfungen genutzt. Allerdings wird er viel zu häufig (einmal pro Transport, einmal pro Aufgabe, einmal pro ToC) aufgerufen. Eine Pufferung (ca. 60 Sekunden Gültigkeit des Puffers, implementiert mittels Enhancement-Technik) wirkt hier wunder.

Funktionsbaustein /TMWFLOW/BCO_READ_OBJECTS wird für das Lesen der Objektdefinitionen genutzt. Mittels Modifikation können folgende Optimierungen durchgeführt werden, die die Performance signifikant verbessern:

  • Die Nutzung sortierter interner Tabellen verhindert Full Table Scan.
  • Die Optimierung des SQL-Statements zum Lesen der ausschließlich benötigten Datensätze verhindert das prozessieren aller Datensätze.
  • Das Entfernen des Sortieren-Befehls aus der Loop-Schleife löste die Bremse.

Funktionsbaustein /TMWFLOW/BCO_CHECK_OBJECTS dient zur Durchführung der Objektprüfung durch Vergleich der Liste der kritischen Objekte mit dem Inhalt des zu prüfenden Transportauftrages. Sobald ein Objekt als kritisch identifiziert wird, wird es aus der Liste des Transportauftrageinhaltes in die Liste der kritischen Objekte verschoben. Diese Verschiebung kostet Zeit/Performance. Zudem ist diese Verschiebung u.U. gar nicht gewollt, da ein Objekt ggf. zu mehreren kritischen Objektdefinitionen passen kann und dann auch mehrfach angemahnt (und genehmigt) werden sollte. Folglich sollten alle Löschoperationen auf den internen Tabellen lt_bao6163 und lt_e071k per Modifikation entfernt werden. Außerdem sollten auch hier sortierte interne Tabellen genutzt werden und sofern möglich auf den Vergleichsoperator „contains pattern“ verzichtet werden.

Funktionsbaustein /TMWFLOW/RCK_APPLY_SPECS wird genutzt um die Liste der kritischen Objekte mit den bereits genehmigten kritischen Objekten abzumischen. Hier sollten ebenfalls sortierte interne Tabellen genutzt werden um performanceoptimal zu arbeiten. Zudem ist hier eine Fehlerkorrektur erforderlich, um zu verhindern, dass Genehmigung nicht wieder verloren gehen und um sicherzustellen, dass jede Objekt- oder Subobjektgenehmigung für nur genau dieses Objekt/Subobjekt angewendet wird.

Hier die entsprechendes Code-Snipsel:

FUNCTION /tmwflow/bco_read_objects.
*"----------------------------------------------------------------------
*"*"Local Interface:
*"  IMPORTING
*"     REFERENCE(IV_SPEC_NO) TYPE  /TMWFLOW/BCO_SPEC_NO OPTIONAL
*"  EXPORTING
*"     REFERENCE(ES_BCOOBJS_SPEC_NO) TYPE  /TMWFLOW/VBCOCRI
*"     REFERENCE(EV_NO_OBJECTS_DEFINED) TYPE  FLAG
*"  TABLES
*"      ET_BCOOBJS_TOTAL STRUCTURE  /TMWFLOW/VBCOCRI OPTIONAL
*"      ET_BCOOBJS_OBJ STRUCTURE  /TMWFLOW/VBCOCRI OPTIONAL
*"      ET_BCOOBJS_KEY STRUCTURE  /TMWFLOW/VBCOCRI OPTIONAL
*"----------------------------------------------------------------------

*{   REPLACE        
*\  DATA: lt_bcoobjs      TYPE TABLE OF /tmwflow/vbcocri WITH DEFAULT KEY,
*\        lt_bcoobjs_tmp  TYPE TABLE OF /tmwflow/vbcocri WITH DEFAULT KEY.
  DATA: lt_bcoobjs      TYPE SORTED TABLE OF /tmwflow/vbcocri WITH UNIQUE KEY SPEC_NO LANGU,
        lt_bcoobjs_tmp  TYPE SORTED TABLE OF /tmwflow/vbcocri WITH UNIQUE KEY SPEC_NO LANGU.
*}   REPLACE
  DATA: ls_bcoobjs      TYPE          /tmwflow/vbcocri.

  FIELD-SYMBOLS:    LIKE LINE OF lt_bcoobjs_tmp.

  IF NOT iv_spec_no IS INITIAL.

    SELECT SINGLE * FROM /tmwflow/vbcocri INTO es_bcoobjs_spec_no
      WHERE spec_no EQ iv_spec_no
      AND   langu   EQ sy-langu.
    IF sy-subrc <> 0.

      SELECT SINGLE * FROM /tmwflow/vbcocri INTO es_bcoobjs_spec_no
        WHERE spec_no EQ iv_spec_no.
      IF es_bcoobjs_spec_no IS INITIAL.

        ev_no_objects_defined = 'X'.

      ENDIF.

    ENDIF.

  ELSE.

    REFRESH lt_bcoobjs_tmp.
    REFRESH lt_bcoobjs.

    SELECT * FROM /tmwflow/vbcocri INTO TABLE lt_bcoobjs
      WHERE langu EQ sy-langu.

*{   REPLACE        
*\    SELECT * FROM /tmwflow/vbcocri INTO TABLE lt_bcoobjs_tmp.
    SELECT * FROM /tmwflow/vbcocri INTO TABLE lt_bcoobjs_tmp where spec_no not in ( select spec_no from /tmwflow/vbcocri where langu EQ sy-langu ).
*}   REPLACE

    IF NOT lt_bcoobjs[] IS INITIAL.

      LOOP AT lt_bcoobjs_tmp ASSIGNING .

*{   DELETE         
*\        READ TABLE lt_bcoobjs WITH KEY spec_no = -spec_no TRANSPORTING NO FIELDS.
*\        IF sy-subrc <> 0.
*}   DELETE
*{   REPLACE        
*\          APPEND  TO lt_bcoobjs.
          INSERT  INTO TABLE lt_bcoobjs.
*}   REPLACE
*{   DELETE         
*\        ENDIF.
*}   DELETE

      ENDLOOP.

    ELSE.

      lt_bcoobjs[] = lt_bcoobjs_tmp[].

    ENDIF.

    IF NOT lt_bcoobjs[] IS INITIAL.

*{   DELETE         
*\      SORT lt_bcoobjs BY spec_no.
*}   DELETE
      DELETE ADJACENT DUPLICATES FROM lt_bcoobjs COMPARING spec_no.

      MOVE lt_bcoobjs[] TO et_bcoobjs_total[].

      LOOP AT lt_bcoobjs INTO ls_bcoobjs
        WHERE pgmid_obj  NE space
        AND   object_obj NE space
        AND   obj_name   NE space.

*{   REPLACE        
*\        APPEND ls_bcoobjs TO et_bcoobjs_obj.
*\        SORT et_bcoobjs_obj BY spec_no.
        INSERT ls_bcoobjs INTO TABLE et_bcoobjs_obj.
*}   REPLACE

      ENDLOOP.
      CLEAR ls_bcoobjs.
      LOOP AT lt_bcoobjs INTO ls_bcoobjs
        WHERE mastertype NE space
        AND   mastername NE space.

*{   REPLACE        
*\        APPEND ls_bcoobjs TO et_bcoobjs_key.
*\        SORT et_bcoobjs_key BY spec_no.
        INSERT ls_bcoobjs INTO TABLE et_bcoobjs_key.
*}   REPLACE

      ENDLOOP.

    ELSE.

      ev_no_objects_defined = 'X'.

    ENDIF.
  ENDIF.


ENDFUNCTION.
FUNCTION /tmwflow/rck_check_sm_call.
BEGINENHANCEMENT.

*SAP standard is calling this function module several times during one round trip.
*Since result will only change in case of changing transport request content or changing critical object definition we can assume that check is stable within a short time period.
*To improve performance we check critical objects only once per minute.

    TYPES:
    BEGIN OF ts_buffer,
      IS_trordhc         TYPE /TMWFLOW/TRORDHC,
      IV_sysname         TYPE /TMWFLOW/SYSNAME,
      IV_client          TYPE CTSCLIENT,
      EV_ABORT_EXPORT    TYPE FLAG,
      EV_CRITICAL_OBJECT TYPE FLAG,
      CT_MONI_LOG_ENTRY  TYPE STANDARD TABLE OF BALMI WITH DEFAULT KEY,
      ET_CRITICAL        TYPE STANDARD TABLE OF /TMWFLOW/VRCKAPP WITH DEFAULT KEY,
      timestamp          TYPE timestamp,
    END OF ts_buffer,
    tt_buffer TYPE SORTED TABLE OF ts_buffer WITH UNIQUE KEY IS_trordhc iv_sysname iv_client.

    STATICS:
    ss_buffer TYPE ts_buffer,
    st_buffer TYPE tt_buffer.

    DATA:
      lv_timestamp TYPE TZNTSTMPL,
      lv_date      TYPE sy-datum,
      lv_time      TYPE sy-uzeit.

*Get validty time.
    GET TIME STAMP FIELD lv_timestamp.
    lv_timestamp = CL_ABAP_TSTMP=>SUBTRACTSECS( TSTMP = lv_timestamp secs = 60 ).
    CONVERT TIME STAMP lv_timestamp TIME ZONE 'UTC   ' INTO DATE lv_date TIME lv_time.
*   CONVERT TIME STAMP lv_timestamp TIME ZONE sy-zonlo INTO DATE lv_date TIME lv_time.

*Try to find entry in line buffer.
    IF ss_buffer-is_trordhc = is_trordhc AND ss_buffer-iv_sysname = iv_sysname AND ss_buffer-iv_client = iv_client.

      sy-subrc = 0.

    ELSE.

*Try to find entry in table buffer.
      READ TABLE st_buffer
      INTO ss_buffer
      WITH KEY is_trordhc = is_trordhc iv_sysname = iv_sysname iv_client = iv_client.

    ENDIF.

*Check whether found entry is still valid.
    IF sy-subrc = 0 AND ss_buffer-timestamp >= lv_timestamp.

*Check whether approval was changed since buffer entry creation.
      SELECT SINGLE APPR_TIME
      INTO lv_time
      FROM /tmwflow/rckwork
      WHERE trkorr = is_trordhc-trorder_number AND
            ( APPR_DATE > lv_date OR ( APPR_DATE = lv_date AND APPR_TIME > lv_time ) ).

      IF sy-subrc = 0.

*If it was changed: Forget buffer.
        DELETE TABLE st_buffer FROM ss_buffer.

      ELSE.

*Take result from buffer.
        MOVE:
        ss_buffer-ev_abort_export    TO EV_ABORT_EXPORT,
        ss_buffer-EV_CRITICAL_OBJECT TO EV_CRITICAL_OBJECT,
        ss_buffer-ET_CRITICAL        TO ET_CRITICAL[].

        APPEND LINES OF ss_buffer-CT_MONI_LOG_ENTRY TO CT_MONI_LOG_ENTRY.

        EXIT.

      ENDIF.

    ENDIF.

*Build new buffer entry.
    CLEAR ss_buffer.
    MOVE:
      IS_TRORDHC          TO ss_buffer-IS_TRORDHC,
      IV_SYSNAME          TO ss_buffer-IV_SYSNAME,
      IV_CLIENT           TO ss_buffer-IV_CLIENT,
      CT_MONI_LOG_ENTRY[] TO ss_buffer-CT_MONI_LOG_ENTRY.
*     lv_timestamp        to ss_buffer-timestamp.

    DO 1 TIMES.

ENDENHANCEMENT.

...
Two modifications here:
lt_bcobjt is a sorted table now to improve speed.
"CHECK et_critical IS SUPPLIED" is removed to ensure it will always be calculated.
...

BEGINENHANCEMENT.

    ENDDO.

*Get current timestamp.
    GET TIME STAMP FIELD lv_timestamp.

*Complete buffer entry.
    MOVE:
      lv_timestamp           TO ss_buffer-timestamp,
      EV_ABORT_EXPORT        TO ss_buffer-EV_ABORT_EXPORT,
      EV_CRITICAL_OBJECT     TO ss_buffer-EV_CRITICAL_OBJECT,
      ET_CRITICAL[]          TO ss_buffer-ET_CRITICAL.

    DATA:
      LT_MONI_LOG_ENTRY LIKE CT_MONI_LOG_ENTRY[].

    APPEND LINES OF CT_MONI_LOG_ENTRY FROM LINES( ss_buffer-CT_MONI_LOG_ENTRY ) + 1 TO LINES( CT_MONI_LOG_ENTRY ) TO LT_MONI_LOG_ENTRY.
    MOVE LT_MONI_LOG_ENTRY TO ss_buffer-CT_MONI_LOG_ENTRY.

*Store buffer entry in table buffer and keep it in line buffer.
    MODIFY TABLE st_buffer FROM ss_buffer.
    IF sy-subrc <> 0.
      INSERT ss_buffer INTO TABLE st_buffer.
    ENDIF.

ENDENHANCEMENT.
ENDFUNCTION.
FUNCTION /tmwflow/bco_check_objects.
*"----------------------------------------------------------------------
*"*"Local Interface:
*"  IMPORTING
*"     REFERENCE(IV_SYSNAME) TYPE  /TMWFLOW/SYSNAME
*"     REFERENCE(IV_CLIENT) TYPE  CTSCLIENT
*"     REFERENCE(IV_TRKORR) TYPE  TRKORR
*"     REFERENCE(IV_VERSION) TYPE  SYSAPRL
*"  EXPORTING
*"     REFERENCE(ET_MESSAGE) TYPE  BAPIRETTAB
*"  TABLES
*"      IT_BAO6163 STRUCTURE  BAO6163
*"      IT_E071K STRUCTURE  SCWB_E071K
*"      ET_CRITICAL STRUCTURE  /TMWFLOW/RCKWORK
*"----------------------------------------------------------------------

  DATA: lv_id                  TYPE /tmwflow/rckwork-id VALUE 0.
  DATA: lv_msg_txt             TYPE bapi_msg.
  DATA: ls_critical_export     TYPE /tmwflow/rckwork.
*{   REPLACE        
*\  DATA: lt_bao6163             TYPE STANDARD TABLE OF bao6163 WITH DEFAULT KEY.
  DATA: lt_bao6163             TYPE SORTED TABLE OF bao6163 WITH NON-UNIQUE KEY pgmid object obj_name WITH NON-UNIQUE SORTED KEY fragment components fragid fragment fragname.
*}   REPLACE
*{   REPLACE        
*\  DATA: lt_e071k               TYPE STANDARD TABLE OF scwb_e071k WITH DEFAULT KEY.
  DATA: lt_e071k               TYPE SORTED TABLE OF scwb_e071k WITH NON-UNIQUE KEY pgmid object objname.
*}   REPLACE
  DATA: lt_defined_critical    TYPE STANDARD TABLE OF /tmwflow/vbcocri WITH DEFAULT KEY.
  DATA: lt_critical_export     TYPE STANDARD TABLE OF /tmwflow/rckwork WITH DEFAULT KEY.

  FIELD-SYMBOLS:
              LIKE LINE OF lt_defined_critical,
               LIKE LINE OF lt_bao6163,
            LIKE LINE OF lt_e071k.

  CLEAR et_critical.

  MOVE it_bao6163[] TO lt_bao6163[].
  MOVE it_e071k[]   TO lt_e071k[].

*--------------------------------------------------------------------*
* Get defined critical object in /TMWFLOW/COMSCONF

  CALL FUNCTION '/TMWFLOW/BCO_SPECIFICATIONS'
    EXPORTING
      iv_sys_name = iv_sysname
      iv_client   = iv_client
    TABLES
      et_critical = lt_defined_critical.
  CHECK lt_defined_critical IS NOT INITIAL.


*--------------------------------------------------------------------*
* Check for Workbench object

  LOOP AT lt_defined_critical ASSIGNING 
    WHERE pgmid_obj  <> space
      AND object_obj <> space.

    IF iv_version >= '2.00'.
      CHECK -pgmid_obj = gc_limu
        OR -pgmid_obj = gc_r3tr.
    ENDIF.

*{   INSERT         

*We can improve performance if we are not using patterns.
    IF -obj_name NA '*+'.

      DATA: lv_obj_name LIKE -obj_name.
      lv_obj_name = -obj_name.

      LOOP AT lt_bao6163 ASSIGNING  USING KEY primary_key
            WHERE ( ( pgmid    =  -pgmid_obj
                  AND object   =  -object_obj
                  AND obj_name =  lv_obj_name ) ).

        ls_critical_export-cid         = gc_check_bco.
        ls_critical_export-appr_status = gcs_object_status-critical.
        ls_critical_export-spec_no     = -spec_no.

        ls_critical_export-trkorr      = -trkorr.
        ls_critical_export-fragid      = -fragid.
        ls_critical_export-fragment    = -fragment.
        ls_critical_export-fragname    = -fragname.
        ls_critical_export-pgmid_obj   = -pgmid.
        ls_critical_export-object_obj  = -object.
        ls_critical_export-obj_name    = -obj_name.
        APPEND ls_critical_export TO lt_critical_export.

*\      DELETE lt_bao6163.

      ENDLOOP.

      DATA: lv_fragname LIKE -fragname.
      lv_fragname = -obj_name.

      LOOP AT lt_bao6163 ASSIGNING  USING KEY fragment
            WHERE ( ( fragid   =  -pgmid_obj
                  AND fragment =  -object_obj
                  AND fragname =  lv_fragname ) ).

        ls_critical_export-cid         = gc_check_bco.
        ls_critical_export-appr_status = gcs_object_status-critical.
        ls_critical_export-spec_no     = -spec_no.

        ls_critical_export-trkorr      = -trkorr.
        ls_critical_export-fragid      = -fragid.
        ls_critical_export-fragment    = -fragment.
        ls_critical_export-fragname    = -fragname.
        ls_critical_export-pgmid_obj   = -pgmid.
        ls_critical_export-object_obj  = -object.
        ls_critical_export-obj_name    = -obj_name.
        APPEND ls_critical_export TO lt_critical_export.

*\      DELETE lt_bao6163.

      ENDLOOP.

      CONTINUE.

    ENDIF.

*}   INSERT

    "!!!If subobject (belongs to defined critical object) is changed
    "we also take is as an additional cirtical object
    LOOP AT lt_bao6163 ASSIGNING 
       WHERE ( ( pgmid    =  -pgmid_obj
             AND object   =  -object_obj
             AND obj_name CP -obj_name )
       OR
               ( fragid   =  -pgmid_obj
             AND fragment =  -object_obj
             AND fragname CP -obj_name ) ).

      ls_critical_export-cid         = gc_check_bco.
      ls_critical_export-appr_status = gcs_object_status-critical.
      ls_critical_export-spec_no     = -spec_no.

      ls_critical_export-trkorr      = -trkorr.
      ls_critical_export-fragid      = -fragid.
      ls_critical_export-fragment    = -fragment.
      ls_critical_export-fragname    = -fragname.
      ls_critical_export-pgmid_obj   = -pgmid.
      ls_critical_export-object_obj  = -object.
      ls_critical_export-obj_name    = -obj_name.
      APPEND ls_critical_export TO lt_critical_export.

*{   DELETE         
*\      DELETE lt_bao6163.
*}   DELETE

    ENDLOOP.

  ENDLOOP.


*--------------------------------------------------------------------*
* Check for Customizing object

  CLEAR ls_critical_export.

  LOOP AT lt_defined_critical ASSIGNING 
    WHERE mastertype <> space
      AND mastername <> space.

*{   INSERT         
    IF  NOT -pgmid_key  = space "R3TR
    AND NOT -object_key = space "TABU
    AND NOT -objname    = space "Tablename without * and +
    AND NOT -objname CA '*+'
    AND NOT -mastertype = space "CDAT, VDAT, TABU
    AND NOT -mastername = space. "Clustername, Viewname or Tablename

*Filter 1
      LOOP AT lt_e071k ASSIGNING  USING KEY primary_key
            WHERE pgmid       =  -pgmid_key
            AND   object      =  -object_key
            AND   objname     =  -objname
            AND   mastertype  =  -mastertype.

*Filter 2
        CHECK ( -viewname   IS INITIAL OR -viewname   CP -viewname ) AND
              ( -mastername IS INITIAL OR -mastername CP -mastername ) AND
              ( -tabkey     IS INITIAL OR -tabkey     CP -tabkey ).

        MOVE-CORRESPONDING  TO ls_critical_export.

        ls_critical_export-cid            = gc_check_bco.
        ls_critical_export-appr_status    = gcs_object_status-critical.
        ls_critical_export-spec_no        = -spec_no.
        ls_critical_export-pgmid_key      = -pgmid_key.
        ls_critical_export-object_key     = -object_key.

        APPEND ls_critical_export TO lt_critical_export.

*        DELETE lt_e071k.

      ENDLOOP.

      CONTINUE.

    ENDIF.

*}   INSERT
    "the critical object could be table or view, that means, not both are empty is ok
    IF  NOT -pgmid_key  = space
    AND NOT -object_key = space
    AND NOT ( -objname = space
      AND -viewname   = space )
    AND NOT -mastertype = space
    AND NOT -mastername = space
    AND NOT -tabkey     = space.

      LOOP AT lt_e071k ASSIGNING 
          WHERE pgmid       =  -pgmid_key
          AND   object      =  -object_key
          AND ( objname     =  -objname
          OR    viewname    =  -viewname )
          AND   mastertype  =  -mastertype
*{   REPLACE        
*\          AND   mastername  =  -mastername
          AND   mastername  CP -mastername
*}   REPLACE
          AND   tabkey      CP -tabkey.

        MOVE-CORRESPONDING  TO ls_critical_export.

        ls_critical_export-cid            = gc_check_bco.
        ls_critical_export-appr_status    = gcs_object_status-critical.
        ls_critical_export-spec_no        = -spec_no.
        ls_critical_export-pgmid_key      = -pgmid_key.
        ls_critical_export-object_key     = -object_key.

        APPEND ls_critical_export TO lt_critical_export.

*{   DELETE         
*\        DELETE lt_e071k.
*}   DELETE

      ENDLOOP.

...

ENDFUNCTION.
FUNCTION /tmwflow/rck_apply_specs.
*"----------------------------------------------------------------------
*"*"Local Interface:
*"  IMPORTING
*"     REFERENCE(IV_CID) TYPE  /TMWFLOW/RCK_CID
*"     REFERENCE(IV_TRKORR) TYPE  SCWB_E070-TRKORR
*"     REFERENCE(IV_VERSION) TYPE  SYSAPRL
*"     REFERENCE(IV_SYS_NAME) TYPE  /TMWFLOW/SYSNAME OPTIONAL
*"     REFERENCE(IV_CLIENT) TYPE  /TMWFLOW/CLIENT OPTIONAL
*"  EXPORTING
*"     REFERENCE(ET_MESSAGE) TYPE  BAPIRETTAB
*"  TABLES
*"      TT_BAO6163 STRUCTURE  BAO6163
*"      TT_E071K STRUCTURE  SCWB_E071K
*"----------------------------------------------------------------------

  DATA: lv_flag               TYPE flag.
  DATA: lv_critical_objs      TYPE flag.
  DATA: lv_critical_keys      TYPE flag.
  DATA: ls_request_bao6163    LIKE bao6163.
  DATA: ls_request_scwb_e071k LIKE scwb_e071k.
  DATA: ls_approved_objects   TYPE /tmwflow/rckwork.
*{   REPLACE        
*\  DATA: lt_export_bao6163     TYPE STANDARD TABLE OF bao6163 WITH DEFAULT KEY.
*\  DATA: lt_export_scwb_e071k  TYPE STANDARD TABLE OF scwb_e071k WITH DEFAULT KEY.
  DATA: lt_export_bao6163     TYPE SORTED TABLE OF bao6163 WITH NON-UNIQUE KEY pgmid object obj_name fragid fragment fragname.
  DATA: lt_export_scwb_e071k  TYPE SORTED TABLE OF scwb_e071k WITH NON-UNIQUE KEY pgmid object objname mastertype mastername viewname tabkey.
*}   REPLACE
  DATA: lt_approved_objects   TYPE STANDARD TABLE OF /tmwflow/rckwork.
  DATA: lt_message            TYPE bapirettab.
  DATA: lv_msg_txt            TYPE bapi_msg.

  MOVE tt_bao6163[] TO lt_export_bao6163[].
  MOVE tt_e071k[]   TO lt_export_scwb_e071k[].

*--------------------------------------------------------------------*
* Exclude already approved Critical Objects

  SELECT * FROM /tmwflow/rckwork INTO TABLE lt_approved_objects
    WHERE trkorr        = iv_trkorr
    AND   cid           <> gc_check_mod
    AND   appr_status   = /tmwflow/cl_transport=>c_crit_obj_approved
    AND   appr_user     <> space
    AND   appr_date     <> space
    AND   appr_time     <> space.

  LOOP AT lt_approved_objects INTO ls_approved_objects.
    IF ls_approved_objects-sys_name <> iv_sys_name
      AND ls_approved_objects-client_id <> iv_client.
      CONTINUE.
    ENDIF.


    "Fix IM 1121109 2013 and 1131195 2013 for wrong handling of sub-object
    "Sub-object has own PGMID/OBJECT definition in /TMWFLOW/CMSCONF
    "so we only count it if the PGMID/OBJECT is fully matching
    "refer to function /TMWFLOW/BCO_CHECK_OBJECTS as how it's calculated
*{   INSERT         
      DATA: lv_obj_name LIKE ls_request_bao6163-obj_name.
      lv_obj_name = ls_approved_objects-obj_name.
*}   INSERT
    LOOP AT lt_export_bao6163 INTO ls_request_bao6163
*{   REPLACE        
*\      WHERE pgmid  =  ls_approved_objects-pgmid_obj
*\        AND object =  ls_approved_objects-object_obj.
      WHERE pgmid    = ls_approved_objects-pgmid_obj
        AND object   = ls_approved_objects-object_obj
        AND obj_name = lv_obj_name
        AND fragid   = ls_approved_objects-fragid
        AND fragment = ls_approved_objects-fragment
        AND fragname = ls_approved_objects-fragname.
*}   REPLACE
*     OR  ( fragid   =  ls_approved_objects-fragid
*     AND   fragment =  ls_approved_objects-fragment
*     AND   fragname =  ls_approved_objects-fragname ) ).

*{   DELETE         
*\    "This check is only for workbench critical objects
*\    CHECK ls_approved_objects-object_obj <> space OR ls_approved_objects-fragment IS NOT INITIAL.
*\      IF iv_version >= '2.00'.
*\        "Begin of Change for Novartis by Sawyer 2014/11/25 Incident 691666 2014
*\        IF ls_approved_objects-fragment = 'PMKC' OR
*\           ls_approved_objects-fragment = 'ACGR'.
*\          "Just continue
*\        ELSE.
*\          CHECK ls_approved_objects-pgmid_obj = gc_limu
*\            OR ls_approved_objects-pgmid_obj  = gc_r3tr.
*\        ENDIF.
*\        "End of Change for Novartis by Sawyer 2014/11/25
*\
*\        CHECK ls_request_bao6163-obj_name CP ls_approved_objects-obj_name.
*\      ELSE.
*\        CHECK ls_request_bao6163-obj_name = ls_approved_objects-obj_name.
*\      ENDIF.
*}   DELETE

      MESSAGE s120(/tmwflow/crit_obj)
        WITH ls_request_bao6163-trkorr
             ls_request_bao6163-object
             ls_request_bao6163-obj_name
             ls_approved_objects-appr_user INTO lv_msg_txt.

      message_set sy-msgty sy-msgid sy-msgno lv_msg_txt
                  sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4
                  lt_message.
      APPEND LINES OF lt_message TO et_message.
      REFRESH lt_message.

      DELETE lt_export_bao6163.
      lv_flag = abap_true.
      lv_critical_objs = abap_true.

    ENDLOOP.


    LOOP AT lt_export_scwb_e071k INTO ls_request_scwb_e071k
        WHERE pgmid       =  ls_approved_objects-pgmid_key
        AND   object      =  ls_approved_objects-object_key
        AND   objname     =  ls_approved_objects-objname
        AND   mastertype  =  ls_approved_objects-mastertype
        AND   mastername  =  ls_approved_objects-mastername
        AND   viewname    =  ls_approved_objects-viewname
        AND   tabkey      =  ls_approved_objects-tabkey.

      MESSAGE s120(/tmwflow/crit_obj)
        WITH ls_request_scwb_e071k-trkorr
             ls_request_scwb_e071k-mastertype
             ls_request_scwb_e071k-mastername
             ls_approved_objects-appr_user
      INTO lv_msg_txt.
      message_set sy-msgty sy-msgid sy-msgno lv_msg_txt
                  sy-msgv1 sy-msgv2 sy-msgv3 sy-msgv4
                  lt_message.
      APPEND LINES OF lt_message TO et_message.
      REFRESH lt_message.

      DELETE lt_export_scwb_e071k.
      lv_flag = abap_true.
      lv_critical_keys = abap_true.

    ENDLOOP.

    IF lv_flag <> abap_true.
      DELETE FROM /tmwflow/rckwork
        WHERE trkorr = ls_approved_objects-trkorr
        AND   id     = ls_approved_objects-id.

*{   DELETE         
*\      COMMIT WORK.
*}   DELETE
    ENDIF.

  ENDLOOP.
*{   INSERT         
     COMMIT WORK.
*}   INSERT


  IF lv_critical_objs = abap_true.
    REFRESH tt_bao6163.
    MOVE lt_export_bao6163[] TO tt_bao6163[].
  ENDIF.
  IF lv_critical_keys = abap_true.
    REFRESH tt_e071k.
    MOVE lt_export_scwb_e071k[] TO tt_e071k[].
  ENDIF.

ENDFUNCTION.

Die Prüfung eines Transportauftrages mit 40.000 Objekten gegen eine Objektliste mit 40.000 kritischen Objekten dauert jetzt ca. 20 Sekunden statt vorher mehr als 20 Minuten.

Feature Attributes (DNO_CUST04 2.0)

Introduction

Sometimes we need the capability to activate or deactivate a certain feature or to select a feature variant in context of a specific process type or project id. The already existing solution DNO_CUST04 / DNOC_USERCFG or AGS_WORK_CUSTOM are no proper solutions because here we cannot define attribute names & values and we cannot assign attributes to a project id.

Because SAP SE is not able to design and implement a proper solution, we have to do it.

Tables and Maintenance Views

Attribute Name

Table ZAT_N_C | Attribute Name

  • CLIENT | Client
  • NAME | Attribute Name

Table ZAT_N_T | Attribute Name (Text)

  • CLIENT | Client
  • LANGU | Language
  • NAME | Attribute Name
  • TEXT | Attribute Name Description

Attribute Value

Table ZAT_V_C | Attribute Value

  • CLIENT | Client
  • NAME | Attribute Name
  • VALUE | Attribute Value

Table ZAT_V_T | Attribute Value (Text)

  • CLIENT | Client
  • LANGU | Language
  • NAME | Attribute Name
  • VALUE | Attribute Value
  • TEXT | Attribute Value Description

Search Help ZAT_SH | Attribute Values (used for dynamic value list determination in customizing tables)

  •  ZAT_V_C-NAME | I+E | | Attribute Name
  • ZAT_V_C-VALUE | E | 1 | Attribute Value
  • ZAT_V_T-TEXT | | 2 | Attribute Value Description

Attribute Assignment

Table ZAT_A_C | Attribute Assignment

  • CLIENT | Client
  • PROCESS_TYPE | Process Type
  • PROJECT_ID | Project ID
  • NAME | Attribute Name
  • VALUE | Attribute Value

View ZAT_PT_V | Attribute Assignment on Process Type level (transportable)

  • CLIENT | H | Client
  • PROCESS_TYPE | | Process Type
  • PROJECT_ID | H | = “ | Project ID
  • NAME | | Attribute Name
  • VALUE | | Attribute Value
  • PROCESS_TYPE_TEXT | R | Process Type Description
  • NAME_TEXT | R | Attribute Name Description
  • VALUE_TEXT | R | Attribute Value Description

View ZAT_PT_V | Attribute Assignment on Project level (not transportable)

  • CLIENT | H | Client
  • PROCESS_TYPE | | Process Type
  • PROJECT_ID | <> “ | Project ID
  • NAME | | Attribute Name
  • VALUE | | Attribute Value
  • PROCESS_TYPE_TEXT | R | Process Type Description
  • NAME_TEXT | R | Attribute Name Description
  • VALUE_TEXT | R | Attribute Value Description

View Cluster ZAT_VC | Attributes

  • ZAT_N_C | Attribute Name
    • ZAT_V_C | Attribute Value

API (Class ZAT_CL)

CHECK_ATTRIBUTE

Purpose:

  • Check for Name and Value of an attribute

In:

  • Process Type
  • Project ID
  • Name
  • Value

Out:

  • Boolean

Content:

  • Check for attribute and context in table ZAT_A_C

GET_VALUE

Purpose:

  • Get Value of an attribute

In:

  • Process Type
  • Project ID
  • Name

Out:

  • Value

Content:

  • Read first value for given context and attribute name from table ZAT_A_C. Sort by process type (descending) and project id (descending) to enable overlapping capability.

Overlapping Capability:

  • PROCESS_TYPE | PROJECT_ID
  • X X
  • X O
  • O X
  • O O

GET_ATTRIBUTES

Purpose:

  • Get complete list of active attributes

In:

  • Process Type
  • Project ID

Out:

  • Table of Name Value pairs
  • Table of Strings

Content:

  • Read all attribute names and values for given context from table ZAT_A_C.
  • Concatenate name and value separated by slash (if string table result is requested).

GET_ATTRIBUTES_FOR_TRANSACTION

Purpose:

  • Get complete list of active attributes for a transaction

In:

  • Transaction GUID

Out:

  • Table of Name Value pairs
  • Table of Strings

Content:

  • Get process type using method cl_hf_helper=>get_proc_type_of_chng_doc.
  • Get project id using method cl_al_crm_cm_utility=>read_project_id.
  • Get result data calling method GET_ATTRIBUTES

Business Object Attribute (used by PPF actions)

SWO1 -> Enhancement of BUS2000116 (Service Process) -> Attribute „Features“

Data Reference: BDI_LOG-COMM (String table)

In:

  • Transaction Guid

Out:

  • Feature List

Content:

  • Call method GET_ATTRIBUTES_FOR_TRANSACTION

Note:

  • This attribute can be used in ppf schedule and start conditions
  • Usually we are using operator „CE“ to check for a certain name value pair („NAME/VALUE“). However pattern search (with asterisk and plus is also working).

SPRO / IMG

  • Attribute Definition (Name & Values): Define feature attributes with name and possible values.
  • Attribute Assignment on Process Type level (transportable): Assign feature attributes to process type in order to activate feature or choose feature variant for a specific process type. Note. This configuration is transportable.
  • Assign Attribute on Project level (not transportable): Assign feature attribute to project in order to activate feature or to choose feature variant. Note: This configuration is not transportable. Note: This configuration will overwrite configuration of process type level in case application wants to read the value for a specific attribute name. This configuration will be merged with configuration of process type level in case application wants to check a specific attribute (name & value) or wants to read complete list of active attributes.
  • Optionally we can add DNO_CUST04 and AGS_WORK_CUSTOM here (several existing IMG activities).

Transport-Related Checks (available with SAP Solution Manager 7.2 SPS 3+)

With SAP Solution Manager 7.2 SPS 3 there is a new assignment block available. This new assignment block is called „Transport-Related Checks“ (german: „Transportbezogene Prüfungen“). It merges the results of the Cross-System Object Lock (CSOL), Downgrade Protection (DGP), Critical Object Check (COC), ABAP Test Cockpit (ATC) and Code Inspector (CI) to one place. Additionally it provides a feature to implement Customer-Specific checks (CUC) as BADI implementation.

This is an improvement which will simplify the Change Request Management solution significantly. But …

  • The previously existing assignment blocks for DGP, COC or ATC/CI are no longer valid because they are part of the new assignment block.
  • The checks are not harmonized in one framework. That mean that DGP and COC and ATC still have their own approval feature. DGP can be approved on conflict, event and system level. COC can be approved on conflict level. ATC can be approved on issue level. CUC cannot be approved yet.
  • The checks are not harmonized in one framework. That mean that CSOL/DGP, COC, ATC/CI and CUC are triggered at different events. COC and ATC/CI are still not supported on transport import. On the other side COC and CUC are now supported on object save (analogously to CSOL).
  • The checks are not harmonized in one framework. That mean, that there is no unified customizing setting to activate these checks for specific events, landscapes, systems or clients. Only DGP has the capability to activate or deactivate checks on event, landscape, system or client level. COC and ATC/CI can be activated on system level only. CUC needs to implement an own customizing table to enable flexible configuration of the custom-specific checks.
  • When upgrading to SAP Solution Manager SPS 3, you have to run WCF_RT_COMP and WCF_CC. You also have to adjust your UI configurations for Change Documents and Change Cycles and to synchronize UI personalization. Otherwise the new assignment block will not be available or not be visible.

Official documentation:

SAP Help: Transport-Related Checks

Using IBase Components in Change Requests

Requirement

We want to display and select IBase Components in Change Requests.

Challenge

In SAP Standard IBase Components are not supported on CR level, only on CD Header level and CR Item Level (Scope Assignment Block). Therefore there is not only a UI configuration to do.

Solution

We can reuse the solution already implemented for Change Documents.

However, this is a dirty solution, because it contains one modification, one modified enhancement and two copy-past source code clones.

This is acceptable as temporary solution only till SAP will implement it in Standard. Let’s hope it will happen soon.

Steps

  1. Exchange Context Node Controller of AIC_CMCR_H/AICCMCRHeaderEF-BTREFOBJMAIN from CL_SRQM_H_BTREFOBJ_CN to CL_AIC_CMCD_IBASE_CN. Use the enhancement technique on context node controller level to do that. (We have to do it manually because of technical reasons).
  2. Generalize context node controller CL_AIC_CMCD_IBASE_CN to work with CDs and CRs. Therefore correct definition of attribute MR_VIEW_CONTROLLER from CL_AIC_CMCD_AICCMCDHEADER_IMPL to CL_SRQM_RFC_REQUESTFORCH0_IMPL (or OBJECT) by modification.
  3. Add component usage CUSolmanIbaseValueHelp to AIC_CMCR_H and implement view controller methods OP_FINDIBASECOMPONENT and EH_ONSELIBASECOMPONENT analogous to AIC_CMCD_H by copy & past.
  4. Configure Status Dependent Input Readiness (SPRO -> … -> Adjust UI objects by User Status) for UI element „IBASE_COMPONENT“ to make fields editable at the right time (usually analogous to Project ID).
  5. Configure UI and make fields //BTREFOBJMAIN/IBINSTANCE + //BTREFOBJMAIN/IBINSTANCEDESC visible and editable.
  6. Copy Control is usually working fine because the hidden fields are already used in Standard CR to store IBase Component copied from preceeding Incident.
  7. Steps 1 – 5 are needed for editability and selectability. For display only step 5 is sufficient.

Using Substatus / Status Reason / Closure Codes for ChaRM

SAP Solution Manager IT Service Management is using Substatus or Status Reason to give end-users the possibility to specify why the current status is choosen. This is a very good feature which can be used for initial status (Why transaction is created?) final status (Why transaction is closed/withdrawn?), approval and confirmation status (Why it is approved/confirmed/rejected?). The status „Sucessfully Tested“ or „Back to Development“ is also a confirmation status in this meaning.

We don’t want to discuss here, why SAP SE introduced a new concept of substatus / status reason which was already existing in SAP CRM long time ago and which is heavily used by leads, opportunities, … This is another topic which is out of scope of this post.

In this post I want to tell you how to enable this feature for Change Request Management, because it is helpful for ChaRM as well.

  1. Configuration of substatus can be done like for ITSM. No additional customizing table is needed.
  2. Substatus is available as field /AICRM/REASON_ID of table CRMD_SERVICE_H. This is true for ITSM and ChaRM. No field enhancement is needed. If we want to activate processing/change logging for this field we just have to configure it using these technical information.
  3. Substatus is available as field //BTADMINH/EXT./AICRM/REASON_ID in UI configuration of details form. This is true for ITSM and ChaRM (CR and CD). We just need to make the field visible. However ChaRM is not supporting any value help or input readiness check. This needs to be implemented (see below).
  4. Substatus is available as Search Criteria and Search Result List Field. This is true for ITSM and ChaRM (CR and CD). We just need to make the field visible. However ITSM and ChaRM are not supporting any value help (search criteria) and key to text conversion (result list field). This needs to be implemented (see below).
  5. We still have the issue, that the status change is performed by ppf actions in ChaRM. Therefore we have no chance to maintain the substatus / status reason /closure code on change to a final status, because the transaction is final after status change. Only a popup solution can help here which will need a medium-size development (see linked document).

Full Documentation: ChaRM Substatus.pdf (2.3 MiB)


To enable value help and input readiness check, we need to implement all relevant getter and setter methods of AIC_CMCR_H/AICCMCRHeaderEF-BTADMINH./AICRM/REASON_ID and AIC_CMCD_H/AICCMCDHeaderEF-BTADMINH./AICRM/REASON_ID. To avoid copy past of source code we can alternatively change the inheritance hierarchy. 1. Enhance context node controller of AIC_CMCR_H/AICCMCRHeaderEF-BTADMINH and AIC_CMCD_H/AICCMCDHeaderEF-BTADMINH. 2. Exchange super class CL_SRQM_H_BTADMINH_CN by CL_AIC_INCI_INCIDENTHEADE_CN03. 3. Modify or replace code of method CL_AIC_INCI_INCIDENTHEADE_CN03->IF_BSP_MODEL~INIT and catch exception if cast of owner fails.

 METHOD if_bsp_model~init.

    CALL METHOD super->if_bsp_model~init
    EXPORTING
      ID    = ID
      owner = owner.

*We are reusing BTBadminH Context Node of Incident for Change Request and Documents.
*In this case the cast will fail because of the wrong view controller class.
*We dont need a working solution in this case. Therefore we just need to catch the exception.
    CATCH SYSTEM-EXCEPTIONS MOVE_CAST_ERROR = 1.
    mo_controller ?= owner.
    ENDCATCH.

    EXIT. "needed if this is an enhancement at the beginning of the method instead of a modification.

  ENDMETHOD.

To implement a value help for the Status Reason search criteria, we have to implement method GET_V_/AICRM_REASON_ID for view controller of AIC_CMCD_S/SearchQueryView and AI_CMCR_S/CMSR with following content:

METHOD get_v_/aicrm/reason_id.

  DATA:
    lt_list_proc_type  TYPE crmt_process_type_tab,
    lt_range_proc_type TYPE RANGE OF crmt_process_type,
    ls_range_proc_type LIKE LINE OF lt_range_proc_type.

  FIELD-SYMBOLS:
     LIKE LINE OF lt_list_proc_type.


* Get all relevant process types (see value help getter for process_type)
  me->get_all_proc_type( IMPORTING et_proc_type = lt_list_proc_type  ).
*  lt_list_proc_type = me->get_all_proc_type( ).

*Build select option.
  LOOP AT lt_list_proc_type ASSIGNING .
    ls_range_proc_type-sign = 'I'.
    ls_range_proc_type-option = 'EQ'.
    ls_range_proc_type-low = .
    APPEND ls_range_proc_type TO lt_range_proc_type.
  ENDLOOP.

*Get all possible entries.
  SELECT DISTINCT reason_id AS key txt30 AS value
    INTO CORRESPONDING FIELDS OF TABLE cs_result-ddlb_options
    FROM aic_stat_reasont
   WHERE spras = sy-langu AND
         reason_id IN ( SELECT reason_id
                          FROM aic_stat_reason
                         WHERE user_stat_proc IN ( SELECT user_stat_proc
                                                     FROM crmc_proc_type
                                                    WHERE process_type IN lt_range_proc_type ) )
   ORDER BY reason_id.

*Add empty line.
  APPEND INITIAL LINE TO cs_result-ddlb_options.

ENDMETHOD.

To implement a key to text conversion for the Status Reason result list field, we have to implement method GET_/AICRM_REASON_ID for context node controller of AIC_CMCD_S/SearchQueryView-BTADMINH and AI_CMCR_S/CMSR-BTADMINH with following content:

METHOD get_/aicrm/reason_id.

  DATA: lr_current TYPE REF TO  if_bol_bo_property_access,
        lv_key     TYPE         aic_reasonid.

*Get entity.
  IF iterator IS BOUND.
    lr_current = iterator->get_current( ).
  ELSE.
    lr_current = collection_wrapper->get_current( ).
  ENDIF.

*Get key.
  lv_key = lr_current->get_property_as_string( iv_attr_name = '/AICRM/REASON_ID' ).

*use key as value if text cannot be found.
  value = lv_key.

*Try to find text.
  SELECT SINGLE txt30
    INTO value
    FROM aic_stat_reasont
    WHERE reason_id = lv_key AND
          spras = sy-langu.

ENDMETHOD.

Full Documentation: ChaRM Substatus.pdf (2.3 MiB)

How to allow or prevent status change based on phase of change cycle?

The phase control of change cycles is allowing or disallowing certain transport related activities dependent on the current phase. Sometimes the corresponding status change will be allowed or disallowed.

Some famous examples are:

  • Development without Release / Test / Go Live Preparation:
    • Normal Changes cannot be switched from „In Development“ to „To Be Tested“
  • GoLive:
    • Normal Changes cannot be switched from „In Development“ to „To Be Tested“
    • Urgent Changes cannot be switched from „In Development“ to „To Be Tested“

You might want to have some more status change control dependent on the phase of the change cycle. In other words: You want to allow or prevent a switch to a certain status in Normal Change or Urgent Change if the change cycle is or isn’t currently in a specific phase.

Good news:

This is just configuration. In other words: We are able to allow or restrict status changes dependent on change cycle phases. With the following steps I will guide you thru the configuration of an example:

  1. Define Task List action Z_IN_GO_LIVE_ONLY and Z_NOT_IN_GO_LIVE in view /TMWFLOW/TPCACTS.
  2. Allow Task List action Z_IN_GO_LIVE_ONLY in phase GO_LIFE only. Allow Task List action Z_NOT_IN_GO_LIVE in all phases except GO_LIFE. View cluster /TMWFLOW/VC_PHMD is to be used here.
  3. Map Task List action to ChaRM action ZIGLO_SMMJ and ZNIGL_SMMJ in view cluster /TMWFLOW/VC_CPVR (for path CRMW -> SMMN or SMDV).
  4. Define ChaRM action ZIGLO and ZNIGL in view TSOCM_ACTIONS and TSOCM_ACT_DEF. Assign class CL_CHM1_INSTANCE here. The message class and number can be empty but the ChaRM integration flag needs to be set to flag it as tasklist resp. transport related action.
  5. Implement a dummy BADI implementation for these actions. These implementations just need to exist and to be active. They don’t need to do anything (method body can/should be empty).
  6. Assign ChaRM action ZIGLO_SMMJ or ZNIGL_SMMJ to the target status of your Change Transaction in view cluster AIC_SETTINGS corresponding to your requirements. It does not matter whether this action is defined as early or late action since it does nothing.
  7. Assign ChaRM check condition CHECK_ACTION_PHASE to the target status of your Change Transaction and configure it as cancel action (the status change will be cancelled, if the check fails). This setup is also part of view cluster AIC_SETTINGS which can be accessed via SM34 of SPRO.
  8. Repeat or adjust these steps for other phases, actions or transaction types.

Result: Whenever the end-user is performing a status change to the target status, the check condition CHECK_ACTION_PHASE will be triggered and therefore check whether there is an ChaRM action assigned to the target status which is not allowed in the current change cycle phase. This check will find action ZIGLO or ZNIGL. This action will be translated to action Z_IN_GO_LIVE_ONLY or Z_NOT_IN_GO_LIVE and checked against the current change cycle phase using the Task List action assignment configured in step 2. The action itself is doing nothing.

In case you configured ChaRM action ZIGLO: The status change is only possible if the change cycle is in phase „Go Live“.

In case you configured ChaRM action ZNIGL: The status change is only possible if the change cycle is NOT in phase „Go Live“.

If you want to check more than one change cycle phases (e.g. Test or Go Live), you can combine several ChaRM actions. However, this make sense for ZNIGL and similar action only. If you combine ZIGLO and similar actions at least one check will always fail and therefore preventing the status change. If you want to configure a generic solution, you have to configure actions for every change cycle phase: NOT_IN_DEV_W/O_REL, NOT_IN_DEV_W_REL, NOT_IN_TEST, …

Phase of change cycle is preventing execution of transport related activity. How to change this behavior?

The phase control of change cycles is allowing or disallowing certain transport related activities dependent on the current phase.

Some famous examples are:

  • Development without Release / Test / Go Live Preparation:
    • Transport Request of Normal Changes cannot be released
    • Transport of Copies of Normal Changes cannot be created and released
  • GoLive:
    • Transport Requests of Normal Changes cannot be released
    • Transport of Copies of Normal Changes cannot be created and released
    • Transport Requests of Urgent Changes cannot be released
    • Import All into Test is not allowed
    • Import of Urgent Changes into Test or Prod is not allowed
    • Only in this phase an Import All in Production is allowed

When implementing Change Requests in an agile manner like SCRUM, this phase based transport control is not wanted. Especially the Go Live phase is a critical thing because we need to switch to this phase to be able to import all transports into production but at the same time developers are blocked in continuing their development.

Good news:

This is just configuration. In other words: We are able to remove these restrictions and allow production import in „Development with Release“ or Transport Request release in phase „Go Live“.

  1. Call SM34
  2. Open view cluster /TMWFLOW/VC_PHMD
  3. Select phase model (e.g. DEVRL or MNTCL)
  4. Select phase (e.g. DEVELOP_AND_RELEASE or GO_LIFE)
  5. Add or remove action (e.g. SM_IMP_PROD or RC_TR_RELEASE)

Caution: This configuration is delivered by SAP. It is officially not allowed to change these settings. It might happen that you will lose SAP support for SAP incidents in this area. If you remove some entries they might be restored after activating object piece list in SOLMAN_SETUP again which is a regular activity after Support Package upgrade.

Note: If you want to allow creation and release of Transport of Copies, you need to allow Transport Request release. If you still want to disallow release of original Transport Request, you need to prevent the corresponding status change dependent on the current change cycle phase. This additional setup is described in another blog.

ChaRM should ignore a Transport Request. What to do?

Issue:

  1. You deleted a transport request manually but ChaRM is still checking it.
  2. You implemented something but you now want to ignore the corresponding transport request. However you don’t want to undo all implementation steps manually and to send the build and undo transport request to production.

Note:

  1. The following solutions are workarounds.
  2. You should never delete transport requests manually. Only ChaRM should delete transport requests.
  3. You should never reject undo activities. All changes need to be send to production even undo activities.

Solution:

  1. Decouple Transport Request even if this feature is not configured for Change Documents or event decoupling is not allowed for the current CD Status.
    http://scn.sap.com/docs/DOC-65069
  2. Delete assignment between TR and CD (from table TMWFLOW/TRORDHC) using report /TMWFLOW/TRANSPORT_DELETE after implementation of SAP note 2009859: ChaRM: deleted transport request still exists in ChaRM table.

Authority Check on Execution of Task List Tasks

All transport activities performed by a Change Request Management action, by the IT Operator or by batch jobs are tunneled thru the task list. For every transport activity there exist a specialized task in the task list on header, footer or system role level.

For some of these tasks an authority check is performed on execution, for some not.

Why???

For some of these tasks an authority check against following authority objects will be performed on task execution:

  • /TMWFLOW/H Change Request Management: Task in Header
  • /TMWFLOW/D Change Request Management: Task in Development Systems
  • /TMWFLOW/O Change Request Management: Task in Follow-On Systems
  • /TMWFLOW/P Change Request Management: Task in Production Systems
  • /TMWFLOW/R Change Request Management: Task in Retrofit Systems
  • /TMWFLOW/S Change Request Management: Task in Single Systems
  • /TMWFLOW/F Change Request Management: Task in Footer

However, only following tasks are checked by SAP standard (SM 7.1 SP 11):

  • 1000 REQUEST_CREATE /TMWFLOW/SCMA_TRORDER_CREATE
  • 1500 REQUEST_DECOUPLE /TMWFLOW/SCMA_TRORDER_DECOUPLE
  • 1600 REQUEST_ASSIGN /TMWFLOW/SCMA_TRORDER_ASSIGN
  • 1700 REASSIGN_CHANGE /TMWFLOW/SCMA_REASSIGN_CHANGE
  • 1900 REQUEST_REASSIGN /TMWFLOW/SCMA_TRORDER_REASSIGN
  • 2000 TASK_CREATE /TMWFLOW/SCMA_TRTASKS_CREATE
  • 3000 REQUEST_RELEASE /TMWFLOW/SCMA_TRORDER_RELEASE
  • 4000 REQUEST_IMPORT /TMWFLOW/SCMA_TRORDER_IMPORT
  • 5000 CRIT_OBJ_APPROVE /TMWFLOW/SCMA_CRIT_OBJ_APPR
  • 6000 UC_IN_OTHER_SYSTEMS /TMWFLOW/SCMA_TRIMP_SYNC_TEST
  • 7000 LOGON /TMWFLOW/SCMA_RSRLOGIN
  • 8000 CTS_PROJECT_RELEASE /TMWFLOW/SCMA_CTS_RELEASE
  • 9000 QUEUE_PREPARATION /TMWFLOW/SCMA_QUEUE_PREPARE
  • 9100 QUEUE_IMPORT /TMWFLOW/SCMA_QUEUE_IMPORT

Because of technical/historical reasons, the checks for 1700, 1900 5000 are done against /TMWFLOW/D instead of /TMWFLOW/H. Maybe this will be changed in SAP Solution Manager 7.2 and that is why there already exist the not used authority objects /TMWFLOW/H and /TMWFLOW/F.

What to do if we want to have authority checks for other SAP standard tasks or for customer specific tasks?

  1. Maintain table /TMWFLOW/TSKPRGC (Mapping of task report name to task id). The id should be the same as the id used in task list definition. This customizing alignment is not obligatory but would be nice.
  2. Maintain table /TMWFLOW/AUTTSKC (Extend value help for field /TMWFLOW/T of the mentioned authority objects). The description of the task should be equal to the task list definition. This customizing alignment is not obligatory but would be nice.
  3. If the task is defined on header or footer level, you might need to do a modification to map it to /TMWFLOW/D. The authority check is always done using function module /TMWFLOW/TASKLIST_AUTH_CHECK. This function module is called at line 559+ of /TMWFLOW/TASK_START1 and line 222+ of IF_EX_SCMA_TREE_STATUS~ACTION_ALLOWED of class /TMWFLOW/CL_IM_SCMA_STATUS. At these code sections, you will find the mentioned system role mapping. Maybe a better place to do the mapping by enhancement instead of modification is at the beginning of function module /TMWFLOW/TASKLIST_AUTH_CHECK.

Additionally to these authority checks, function module /TMWFLOW/TASKLIST_AUTH_CHECK is also checking B_SMAN_WPL and /TMWFLOW/M on opening of task list or on changing phases. Therefore please ensure to add these authorities to your PFCG roles if needed.

In case you want to add authority checks for SAP standard tasks, you should use following task ids since these IDs are already hard coded in class interface /TMWFLOW/CL_CS_TL_TASK:

  • 1800 IGNORE_DGP_CONF /TMWFLOW/SCMA_IGNORE_DGP_CONF
  • 2100 REQUEST_DELETE /TMWFLOW/SCMA_TRORDER_CLEAR
  • 2200 REPAIR_IMPORT_FLAG /TMWFLOW/SCMA_SET_REPAIR_FLAG
  • 3100 CLUSTER_RELEASE
  • 3200 CLUSTER_IMPORT
  • 4100 PRELIMNRY_IMPORT /TMWFLOW/SCMA_PRELIMNRY_IMPORT

Change Request Management RollOut Guide

Leitfaden für das Anbinden, Verändern oder Bauen von ChaRM-Satelliten-Landschaften

Die in diesem Leitfaden beschriebenen Aktivitäten sind zu tun wenn

  • Eine bestehende SAP-Lösungs-Landschaft an das SAP Solution Manager Change Request Management angebunden werden soll.
  • Eine bestehende an das SAP Solution Manager Change Request Management angebundene SAP-Lösungs-Landschaft verändert werden soll (z.B. Aufbau von dauerhaftem Projekt- und Konsolidierungssystem).
  • Eine bestehende an das SAP Solution Manager Change Request Management angebundene SAP-Lösungs-Landschaft verändert werden soll (z.B. Aufbau von temporärem Wartungs- und Qualitätssicherungssystem. Bisherige Wartung wird für Projekt genutzt.).
  • Eine bestehende an das SAP Solution Manager Change Request Management angebundene SAP-Lösungs-Landschaft verändert werden soll (z.B. Verlängerung des Wartungsstrangen um ein zusätzliches Qualitätssicherungs- oder Vorproduktionssystem).
  • Eine Demolandschaft im SAP Solution Manager Entwicklungssystem angelegt werden soll.
  • Ein Releasezyklus abgeschlossen und ein neuer Releasezyklus angelegt werden soll.
Change Request Management RollOut Guide.pdf (571.8 KiB)

Change Request Management Downgrade Protection Handbuch

Handbuch zur Steuerung, Überwachung und Vermeidung von Parallelentwicklungen

Systemübergreifende Objektsperre / Cross System Object Lock / CSOL

Die „Systemübergreifende Objektsperre / Cross System Object Lock / CSOL“ ist eine Funktion des SAP Solution Manager Change Request Management. Sie gewährleistet, dass ein Objekt bei Änderung in einem verwalteten System im zentralen SAP-Solution-Manager-System gesperrt wird. Spätestens beim Speichern dieser Änderung wird der Entwickler/Customizer über aktuell laufende parallele Anpassungen am selben Objekt informiert und kann seine Änderung ggf. gar nicht oder nur im fremden Änderungsvorgang speichern. Hierdurch werden Importprobleme von vornherein ausgeschlossen bzw. der Implementierer wird im Vorfeld über die Gefahr informiert.

Downgrade-Schutz / Downgrade Protection / DGP

Der „Downgrade-Schutz / Downgrade Protection / DGP“ ist eine Funktion des SAP Solution Manager Change Request Management. Die Funktion dient der Nachverfolgung von Objektänderungen und deren Transport durch die gesamte Lösungslandschaft. Konflikte und daraus resultierende potentielle und tatsächliche Downgrade-Risiken (z.B. Überholen eines Vorgängers oder Überschreiben eines Nachfolgers) werden identifiziert, bewertet, gemeldet und müssen explizit vom Change- / Release-Manager genehmigt werden. Hierdurch werden Importprobleme proaktiv verhindert bzw. der Change- / Release-Manager wird im Vorfeld über die Gefahr informiert.

Projektschnittmengenprüfung / Project Intersection Check / PIC

Wenn Sie in einer Systemlandschaft mit mehreren parallelen Projekten arbeiten, die Projekte aber nicht vollständig disjunkt halten können, dann müssen Sie Abhängigkeitsbeziehungen zwischen den Transportaufträgen definieren. Beim Import von Transportaufträgen werden die Abhängigkeitsbeziehungen ausgewertet und das System weist die Transport­administration automatisch darauf hin, dass sie die Menge der zu importierenden Aufträge vergrößern muss, um die korrekte Importreihenfolge zu erhalten. Die Funktion „Projekt­schnitt­mengenprüfung / Project Intersection Check / PIC“ dient der automatischen Identifikation technisch bedingten Transportabhängigkeiten, der manuellen Vormerkung von logischen Transportabhängigkeiten und der Überwachung der Abhängigkeiten beim Import.

Änderungs-und-Transport-System-Analyse / Change- and Transport System Analysis / CTSA

Die „Änderungs-und-Transport-System-Analyse / Change- and Transport System Analysis / CTSA“ dient der Ad-Hoc-Analyse einer Menge von Transportaufträgen, der darin enthaltenen Objekte und deren Umfeld. Mit Hilfe dieser Analyse können vor dem Projektimport Abhängigkeiten zu anderen Änderungen / Transportaufträge, deren Produktivsetzungen aktuell noch nicht anstehen, identifiziert werden. Der Umfang der zu importierenden Transportaufträge ist anschließend um diese Transportaufträge zu erweitern, da es ansonsten zu kritischen Objektversionsunterschieden zwischen Quell- und Zielsystem und damit einhergehend zu abweichendem Funktionsverhalten, Inkonsistenzen oder Systemabbrüchen kommen kann.

Transportnachverfolgungsmonitor / Transport Tracking Monitor / TRMO

Nach einem GoLive eines größeren Releases bzw. Projektes besteht häufig der Wunsch eines Nachweises der Transport- und Objektkonsistenz. Für eine Schnellanalyse kann die Funktion „Transportnachverfolgungsmonitor / Transport Tracking Monitor / TRMO“ genutzt werden. Sie können hiermit Transportaufträge von dem System, in dem sie angelegt und freigegeben wurden, bis zu dem System, in das sie importiert wurden, nachverfolgen. Dabei lassen sich sowohl Transportdeltas als auch Reihenfolgeverletzungen identifizieren.

Transportausführungsanalyse / Transport Execution Analysis / TEA

Eine ausführliche Analyse der Lösungslandschaft oder des Releases / Projektes ist mit dem Self-Service „Transportausführungsanalyse (für Projekte) / Transport Execution Analysis (for Project) / TEA(P)“ möglich. Diese Analyse kann vor und/oder nach einem GoLive ausgeführt werden. Sie kann auch unabhängig von einem GoLive ausgeführt werden. In jedem Fall erhalten Sie als Ergebnis einen ausführlichen Analysebericht (Word / HTML / PDF) mit konkreten Handlungsanweisungen zur nachhaltigen Sicherung bzw. Verbesserung der Transport- und Objektkonsistenz.

Importqueue-Web-UI – Importprüfungen / Import Queue Web UI – Import Checks / IQIC

Sämtliche zuvor beschriebenen Funktionalitäten sind ausschließlich für ABAP-Änderungen nutzbar. Für Non-ABAP-Änderungen sind sie nicht anwendbar. Ergänzend zur Funktion „Downgrade-Schutz“ und „Projektschnittmengenprüfung“ ist die Funktion „Importqueue-Web-UI – Importprüfungen / Import Queue Web UI – Import Checks / IQIC“ anzuwenden. Diese Funktion unterstützt die Prüfarten „Prüfung auf Vorgänger“ und „Prüfung auf Downgrades“ für alle ABAP- und fast alle Non-ABAP-Transporte. Es erfolgt ausschließlich eine Analyse der aktuell in der Importqueue zum Import anstehenden oder bereits importierten Transportaufträge, weshalb Überholer nur ein einziges Mal erkannt werden – z.B. nur beim Import in das Qualitätssicherungssystem aber nicht beim Import in das Produktionssystem.

Importhistorie-Web-UI – Analysemodus / Import History Web UI – Analysis Mode / IHAM

Ergänzend zur Funktion „Transportnachverfolgungsmonitor“ ist die Funktion „Importhistorie-Web-UI – Analysemodus / Import History Web UI – Analysis Mode / IHAM“ anzuwenden. Diese Funktion identifiziert Reihenfolgeverletzungen, Downgrades und reparierte Downgrades für alle ABAP- und fast alle NonABAP-Transporte. Es erfolgt ausschließlich eine Analyse der Importhistorie, weshalb unter anderem Transportdeltas nicht erkannt werden können.

Download

Change Request Management Downgrade Protection Handbuch.pdf (2.0 MiB)

Checking landscape information in SAP CRM PPF action conditions using BADI CONTAINER_PPF

In SAP Solution Manager Change Request Management we want to work with different status flows dependent on the landscape (in one process type). Therefore we need to use landscape information in Action schedule (and start) conditions.

With BADI implementation ZLIAC_SYSTROLE_EXIST (BADI Definition CONTAINER_PPF) we have the possibility to check the use of specific system roles. To do this, we simply have to define a condition parameter “ZLIAC_SYSTEM_ROLE_EXISTS_<SYSTEM_ROLE>“. Please have a look at transaction MAINT_ROLES for valid system roles.

In our first use case, we want do differentiate between 3-trier and 5-trier landscapes. To do that, we check for existence of system role “3”. This role will only be used in 5-trier landscapes like “D -> T -> 2 -> 3 -> P”. In 3-trier landscapes like “D -> T -> P”, this role will never be used.


*"----------------------------------------------------------------------
*"Methoden Signatur:
*"  Importing
*"    FLT_VAL TYPE OJ_NAME
*"  Changing
*"    CI_CONTAINER TYPE REF IF_SWJ_PPF_CONTAINER
*"    CI_PARAMETER TYPE REF IF_SWJ_PPF_CONTAINER
*"----------------------------------------------------------------------
method IF_EX_CONTAINER_PPF~MODIFY_CONTAINER.

  TYPE-POOLS: socmt.

  data:
    lv_result          type abap_bool,
    lt_parameter       TYPE SWCONTTAB,
    lv_system_role     type /TMWFLOW/PROJECT_SYSTEM_S-SYSTEM_ROLE,
    ls_object          TYPE sibflporb,
    lv_guid            TYPE crmt_object_guid,
    lv_doc_flow_id     TYPE crmt_doc_flow_id_wrk,
    lv_tasklist        TYPE /tmwflow/tasklist,
    lt_system          TYPE TABLE OF /tmwflow/project_system_s,
    lt_transport       TYPE SOCMT_TRORDHC_TYPE.

  field-symbols:
    <fs_parameter> like line of lt_parameter,
    <fs_transport> like line of lt_transport.

*-------------------------------------------------------------------------

*check if classes are bound
  CHECK: ci_container IS BOUND,
         ci_parameter IS BOUND.

*get all parameters
  CALL METHOD ci_parameter->get_values
    RECEIVING
      values = lt_parameter.

*process every matching parameter "ZLIAC_SYSTEM_ROLE_EXISTS_<SYSTEM_ROLE>". Please have a look at transaction MAINT_ROLES for valid system roles.
  loop at lt_parameter[] assigning <fs_parameter> where element(25) = 'ZLIAC_SYSTEM_ROLE_EXISTS_'.

*Crear result because this is a new run.
    clear lv_result.

*This is the first run. Therefore we have to get some information once.
    if lv_system_role is initial.

*Get Change Document
      CALL METHOD ci_container->get_value
        EXPORTING
          element_name = 'BUSINESSOBJECT'
        IMPORTING
          data         = ls_object.

* Extract GUID
      lv_guid = ls_object-instid.

*Exit if it is no valid context.
      if lv_guid is initial.
        return.
      endif.

*Get assigned tasklist
      CALL METHOD cl_hf_helper=>get_bo_tasklist_of_chng_doc
        EXPORTING
          im_change_document_id = lv_guid
        RECEIVING
          return                = lv_doc_flow_id.

      lv_tasklist = lv_doc_flow_id.

*Exit if it is no valid context.
      if lv_tasklist is initial.
        return.
      endif.

*get systems from tasklist
*If we need more information, we have to use /TMWFLOW/PROJECT_GET or /TMWFLOW/PROJECT_READ to get project id and /TMWFLOW/TRANSPORT_TRACK_GET to get extended system information.
      CALL FUNCTION '/TMWFLOW/TASKLIST_SYSTEMS_GET'
        EXPORTING
          id_tasklist       = lv_tasklist
          id_current_track  = 'X'
        TABLES
          et_project_system = lt_system[]
        EXCEPTIONS
          project_not_found = 1
          OTHERS            = 2.

*Exit if it is no valid context.
      if sy-subrc <> 0.
        return.
      endif.

*get transport requests of change document
      CALL METHOD /tmwflow/cl_transport=>get_chng_doc_transp_req
        EXPORTING
          iv_header_guid = lv_guid
        IMPORTING
          et_transp_req  = lt_transport[].

*We are only interested in transport tracks.
*It is OK if we have no transports yet.
      SORT lt_transport[] by transport_track.
      DELETE ADJACENT DUPLICATES FROM lt_transport[] COMPARING transport_track.

    endif.

*Extract system role to be checked now.
    lv_system_role = <fs_parameter>-element+25(1).

*Check every used transport track.
    LOOP AT lt_transport[] assigning <fs_transport>.

*Is system role used?
      READ TABLE lt_system[]
           WITH KEY transport_track = <fs_transport>-transport_track
                    system_role     = lv_system_role
           TRANSPORTING NO FIELDS.

      check sy-subrc = 0.

*Yes system role is in use!!!
      lv_result = abap_true.
      exit.

    ENDLOOP.

*if there are no transport requests, check all project tracks.
    IF sy-subrc NE 0.

      do 1 times.

*Is system role used?
        READ TABLE lt_system[]
             WITH KEY "transport_track = <fs_transport>-transport_track
                      system_role     = lv_system_role
             TRANSPORTING NO FIELDS.

        check sy-subrc = 0.

*Yes system role could be used!!!
        lv_result = abap_true.
        exit.

      enddo.

    endif.

*set output parameter
    CALL METHOD ci_parameter->set_value
      EXPORTING
        element_name = <fs_parameter>-element
        data         = lv_result.
*            RECEIVING
*              retcode      = lv_subrc.

  endloop.

endmethod.

Change Request Management Critical Objects Check and Approval

How to activate and configure the “Critical Objects Check and Approval” feature?

COA is a powerful ChaRM feature to prevent the release of transport requests containing critical objects. It can easily be activated. We need only a little bit UI Configuration (field Critical Objects), Customizing (Actions “Process Critical Object” and Partner Function “Change Manager”), Authority Assignment (Approval Authority) and Master Data Maintenance (Activation + Definition of Critical Objects).
This short guide explains all steps which need to be done. Additional it explains how to mark all changes as critical or how to mark all configuration changes of a certain customizing table as critical independent from the way of maintenance (table, view, view cluster, IMG, SE16, …).

Change Request Management Critical Objects Check and Approval.pdf (808.2 KiB)

Change Request Management Dual Landscape Synchronization with Retrofit

Handbuch zum automatischen Abgleich von systemübergreifenden Parallelentwicklungen mittels Retrofit

In Systemlandschaften, in denen an mehreren Releases gleichzeitig gearbeitet wird, können Änderungen in unterschiedlichen Entwicklungssystemen vorgenommen werden. So können im Entwicklungssystem Neuerungen entwickelt werden und gleichzeitig in einem Wartungssystem für die produktive Systemlandschaft Fehler korrigiert oder Verbesserungen vorangetrieben werden. Wichtig ist in diesem Fall der regelmäßige Abgleich der Systemstände. Da Arbeiten parallel ausgeführt wurden, sind Änderungen nicht über einfache Transporte von Aufträgen ins jeweils andere System möglich, da die Gefahr besteht, dass aktuelle Softwarestände überschrieben werden und Inkonsistenzen entstehen. Um dies zu vermeiden, können Sie einen kontrollierten Abgleich in das jeweilige Zielsystem durchführen. Dieser Vorgang heißt „Parallelabgleich“, „Duale Landschaftssynchronisierung“, „Transportnachbereitung“ bzw. „Retrofit“.

Change Request Management Retrofit.pdf (1.5 MiB)

IT Service Management & Change Request Management My Messages Widget

How to create and use own widget variant configurations?

The “My Messages Widget” feature can be used as very helpful end-user´s inbox. You are able to configure own widget variants to satisfy all business needs.
However, you have to do some developments to make these customer specific variants useable. This short guide explains which development and configurations activities need to be done to make own widget variants useable.

IT Service Management My Messages Widget.pdf (540.6 KiB)