Connector für SAP Business Suite - Entwicklerhandbuch Teil 3 - Integrationsszenario Skripting

Der Connector für SAP Business Suite stellt einige Funktionen für Velocity-Skript zur Verfügung. Die Skript-API des Connectors muss dazu registriert sein. Innerhalb dieser Skript-API stellt der Connector einige Funktionen bereit, die "simpleRFC API", die für den Aufruf von BAPI/RFC-Funktionen in Velocity-Skripten verwendet werden kann. Der Hauptfokus der Skriptfunktionalität des Connector für SAP Business Suite liegt aber auf "Groovy". In Verbindung mit der Integration von SAP-Systemen kann Groovy verwendet werden, um SAP-BAPI/RFC-Funktionen aufzurufen. Damit lassen sich z.B. SAP-Daten generieren bzw. manipulieren (z.B. Kundenstammdaten, Aufträge). SAP-Prozesse (z.B. Workflows) können mit dieser Funktionalität gestart werden. Voraussetzung für die Nutzung der Grovvy-Funktionalität ist ein konfigurierter Connector für SAP Business Suite mit einer aktiven View & Write- oder Developer API-Lizenz.

1. Überblick Szenario SAP Kundenauftrag

Am Beispiel eines SAP-Kundenauftrags wird gezeigt, wie ein typisches Integrationsprojekt ablaufen sollte. SAP-Kundenaufträge werden beispielsweise von Internet-Shops ausgelöst, wenn ein Kunde seinen als Warenkorb zusammengestellten Auftrag speichert.

2. Aufnahme der Anforderungen

In diesem Szenario wird davon ausgegangen, dass ein SAP-R/3-System mit eingerichteter SD- Auftragserfassung existiert. Das SAP-R/3 ist das führende System und gibt die Rahmenbedingungen vor. Im Umkehrschluss bedeutet dies aber auch, dass in der SAP-Welt ein konkretes Ergebnis – der SAP-SD-Auftrag - erwartet wird. Der Kundenauftrag kann mit SAP-Transaktionen über SAP-typische Benutzeroberflächen (dem SAPGUI) erzeugt werden. Für den Kundenauftrag wäre das die Auftragserfassung über die Transaktion "VA01". Ist dies nicht der Fall, also das SAP noch gar nicht in der Lage, die Grundanforderungen mit eigenen Mitteln umzusetzen, ist es für ein Integrationsszenario mit Intrexx noch zu früh. Hier müssen erst die fachlichen Voraussetzungen im SAP (ein SAP-Einführungsprojekt, SAP-Customizing) geschaffen werden. Dies ist nicht Teil dieser Dokumentation sondern Standard-SAP-Geschäft. Die fachlichen Anforderungen an den SAP-Kundenauftrag lassen sich für dieses Beispiel wie folgt formulieren: Der Kunde loggt sich im Intrexx-Portal ein. Im Menü wird ihm die Auftragserfassung zur Verfügung gestellt. Dort stellt er einen Auftrag zusammen, der abschließend an das SAP-System gesendet wird. Im Erfolgsfall ist dem Kunden sofort nach dem Senden die Auftragsnummer mitzuteilen. Der Auftrag soll im SAP-R/3 als SD-Kundenauftrag (Transaktion "VA01") ohne manuelle Zwischenschritte verfügbar sein. Dieses Beispielszenario setzt vereinfachend voraus, dass

3. Simulation des Prozesses in SAP

Da hier von einem fertig eingerichteten SAP-System ausgegangen wird, muss es möglich sein, einen SAP-Kundenauftrag so zu erfassen, als ob er von einem Kunden über eine alternative Oberfläche entgegengenommen wird. Deshalb ist dies in SAP über SAP-Standard-Transaktionen zu simulieren. Für den SAP-SD-Kundenauftrag ist dies die Transaktion "VA01".



Es hat sich dabei bewährt, nur die notwendigsten Eingaben zu ermitteln, die für einen korrekten Auftrag benötigt werden. Für den SAP-SD-Kundenauftrag sind das die folgenden Informationen:

Information Beispiel Herkunft
Auftragsart YTA Konstante, vorgegeben von der SAP-Fachseite
Verkaufsorganisation 1000 Konstante, vorgegeben von der SAP-Fachseite
Vertriebsweg 10 Konstante, vorgegeben von der SAP-Fachseite
Sparte 10 Konstante, vorgegeben von der SAP-Fachseite
Auftraggeber 10000 Kontext des angemeldeten Kunden, Kundennummer
Bestellnummer TEST0001 Eingabe des Kunden, aus Benutzeroberfläche
Bestelldatum 20.08.2008 Eingabe des Kunden, aus Benutzeroberfläche
Material B100000 Eingabe des Kunden, aus Benutzeroberfläche
Menge 10 Eingabe des Kunden, aus Benutzeroberfläche

Je nach Customizing-Einstellungen im SAP-System können eventuell noch weitere Informationen erforderlich sein.



Nach dem Speichern des Auftrags ist durch die SAP-Fachabteilung zu prüfen, ob der Auftrag inhaltlich korrekt und ausreichend ist.



Letzteres sollte unbedingt hier bereits geprüft werden. Beispielsweise kann der SAP-Auftrag auf Basis des eingestellten SAP-Customizing korrekt sein. Da einem Kundenauftrag weitere Prozesse wie Lieferung und Faktura folgen, muss der gesamte Prozess ebenfalls korrekt abgewickelt werden können. Dies zu beurteilen ist Sache der Fachabteilung.

4. Analyse der verfügbaren SAP-BAPI-Funktionen

Im letzten Schritt wurde die SAP-Standard-Transaktion und die benötigten Informationen ermittelt, um den gewünschten SAP-Prozess zu simulieren. In diesem Schritt wird analysiert, welche Funktionen SAP den externen Systemen bietet, um das gleiche Ergebnis – einen identisch aussehenden Kundenauftrag – zu erzeugen. Im SAP-System existieren eine Reihe von Funktionen mit API-Charakter, die von SAP selbst und auch von externen Funktionen verwendet werden können und sollen. Es handelt sich dabei in den meisten Fällen um die sogenannten Funktionsbausteine. Einige dieser Funktionsbausteine sind für externe Systeme verwendbar. Diese haben dann eine zusätzliche Eigenschaft: sie sind per Remote aufrufbar. Man spricht hier von Remote-Function-Calls (kurz RFC), von denen einige Business-Objekt-Charakter haben. D.h. sie sind besonders gekennzeichnet und repräsentieren den objektorientierten Zugriff auf ein SAP-Business-Objekt. Die Gesamtmenge der Business-Objekte und seiner Zugriffsroutinen nennt die SAP AG "Business API" (BAPI). Der einzelne Funktionsbaustein wird hier auch als "BAPI" bezeichnet. Die Business-API mit all ihren BAPI-Funktionsbausteinen werden von SAP empfohlen, wenn es um externen Zugriff auf SAP-Objekte und deren Prozesse geht. Für jedes Integrationsvorhaben sollte deshalb der Weg über die BAPI-Funktionen gehen.

4.1. Transaktion BAPI

Bei der Ermittlung der BAPI-Funktionen für das gewünschte Ergebnis hilft in vielen Fällen die SAP-Transaktion "BAPI". Hier kann recherchiert werden, ob für das gewünschte SAP-Objekt offizielle BAPI-Funktionen angeboten werden. Für das Beispiel SD-Kundenauftrag wird man so sehr schnell fündig.



Für das Beispiel SD-Kundenauftrag anlegen steht beispielsweise das SAP-Business-Objekt "BUS2032" und die Objektmethode (der BAPI Funktionsbaustein "BAPI_SALESORDER_CREATEFROMDAT2") zur Verfügung.

4.2 Business-Object-Repository (BOR)

Das Business-Object-Repository (Transaktion "SWO1") wird vor allem für die SAP-Business-Workflow-Funktionalität verwendet. Alle für den SAP-Workflow wichtigen SAP-Objekte haben hier ein definiertes Business Objekt.



Über die verfügbaren Suchhilfen sollte man das gewünschte Business-Objekt schnell auffinden können.



Hat man das Business-Objekt gefunden, kann man in den Methoden ebenfalls sehr schnell die verwendbaren BAPI-Funktionen identifizieren. Bei diesen kann mit Klick auf eine Schaltfläche direkt zum jeweiligen Funktionsbaustein navigiert werden.

4.3 Suche nach per Remote aufrufbaren Funktionsbausteinen

Falls die vorherigen Bemühungen erfolglos geblieben sind, gibt es die Möglichkeit, in allen per Remote aufrufbaren Funktionsbausteinen nach Stichworten zu suchen. Dazu eignet sich der Funktionsbaustein "RFC_FUNCTION_SEARCH", der über Transaktion "SE37" aufgerufen werden kann.



Über die Eingabeparameter kann hier beispielsweise nach *ORDER* gesucht werden.



Die Ergebnisliste enthält dann alle Funktionsbausteine, die von einer externen Komponente aufgerufen werden könnte. Ob diese den gewünschten Zweck erfüllen, muss natürlich untersucht werden.

4.4 Proxy-Funktionsbausteine

Falls alle vorherigen Versuche erfolglos blieben, um den gewünschten Effekt im SAP-System zu erzielen, gibt es einen letzten Weg: die Individualprogrammierung. Dazu ist zumindest eine Funktionsbaustein-Hülle anzulegen, die als RFC-fähig zu klassifizieren ist. Der Funktionsbaustein muss Aufrufe an andere Funktionsbausteine durchreichen, die vielleicht nicht als per Remote aufrufbar gekennzeichnet sind. Der kundeneigene RFC-Funktionsbaustein agiert dann nur als Proxy. Alternativ kann dieser Funktionsbaustein auch andere im ABAP verfügbare Funktionen (z.B. Unterprogramme) aufrufen oder Batchinput-Mappen generieren und abspielen. Letzteres erfordert natürlich weitreichendes ABAP-Know-how. Weiterhin ist zu bemerken, dass dieses Vorgehen von SAP nicht empfohlen ist und deshalb in diesem Rahmen auch kein Support geleistet wird. Diese Umsetzungsform sollte gewählt werden, wenn keine Alternativen vorhanden sind, dem einsetzenden Kunden das damit verbundenen Risiko bewusst ist und verantwortet werden kann. Aus Gründen der Vereinfachung kann es manchmal auch sinnvoll sein, eigene Proxy-Funktionsbausteine zu verwenden, obwohl offizielle BAPI-Funktionsbausteine für die gewünschte Anforderung existieren. Besonders für externe Systeme ist der Aufruf deutlich übersichtlicher, wenn statt der teilweise sehr umfangreichen Parameter nur die wirklich benötigten gefüllt werden müssen. Proxy-Funktionsbausteine können dann verschiedene BAPI-Aufrufe verbinden und die Parameter ggf. um SAP-Customizing anzureichern (z.B. Ermittlung der richtigen Verkaufsorganisation im SAP).

5. Parameterkonzept

Nachdem klar ist, welche per Remote aufrufbaren Funktionsbausteine – bevorzugt BAPI-Funktionsbausteine – verwendet werden können, muss ein externer Aufruf simuliert werden. Dabei wird bestätigt, ob die vorher ermittelten Informationen wirklich ausreichen, um das gewünschte SAP-Objekt zu erzeugen. Alle Funktionsbausteine bieten über die Transaktion "SE37" eine Testmöglichkeit an, mit der die Funktionen und ihre Parameter geprüft werden können. Hier kann man die Sicht eines externen Systems simulieren. Die in der Funktionsbausteinschnittstelle verfügbaren Parameter sind so zu füllen, wie man sie in der Simulation identifiziert hat.



Die Minimalinformationen aus den Schritten zuvor müssen hier in die entsprechenden Parameterfelder gefüllt werden. Die Testworkbench über Transaktion SE37 unterstützt einfache Parameter, Strukturen und Tabellenparameter. Bei der Identifizierung der richtigen Felder kann Dokumentation zum Funktionsbaustein wertvolle Dienste leisten.



Da das Eingeben der Parameter sehr mühsam sein kann, können solche Eingaben gesichert werden. Über "Testdaten" kann zu einem späteren Zeitpunkt wieder auf Ihre Eingaben zugegriffen werden. Sind alle Parameter eingegeben, so kann der Funktionsbaustein mit der Taste F8 gestartet werden.



Die Funktionsbausteine melden gewöhnlich den Erfolg eines Aufrufs über Exportparameter, z.B. eine vom System erzeugte Belegnummer (siehe rote Markierung). BAPI-Funktionen müssen oft durch den zusätzlichen Aufruf des Funktionsbausteins "BAPI_TRANSACTION_COMMIT" bestätigt werden. Hier tritt sonst der Effekt auf, dass eine Belegnummer o.ä. erzeugt wurde, der Beleg aber nicht im System gefunden wird. Soll diese Art von BAPI-Funktionen getestet werden, so muss man sich entweder mit der erfolgreichen Erzeugung einer Belegnummer zufrieden geben oder im SAP-System den Aufruf des Funktionsbausteines aus einem SAP-Report (Transaktion "SE38") mit anschließendem Commit programmieren. In den meisten Fällen reicht allerdings die erzeugte Belegnummer bereits aus, um von einer erfolgreichen Anlage des SAP-Objektes ausgehen zu können. BAPI-Funktionen haben weiterhin meistens die Eigenschaft, dass Nachrichten über den Erfolg oder Misserfolg der internen Vorgänge in einer Tabelle der Struktur "BAPIRET2" (hier der Parameter "RETURN") dokumentiert werden. Hier werden alle Zeilen vom Typ E, A oder X als Fehler gewertet. In diesen Fällen sollte die Belegnummer im Export ebenfalls fehlen. Innerhalb der Nachrichten finden sich oft detaillierte Hinweise darauf, warum die Funktion nicht erfolgreich verarbeitet werden konnte, z.B. Pflichtfelder nicht gefüllt werden.

6. Design der Benutzeroberfläche

Der nächste Schritt beinhaltet den Erstentwurf einer Benutzeroberfläche für das Integrationsszenario. In diesem Fall sollte der Benutzer alle für die SAP-Funktion benötigten Parameter eingeben bzw. aus dem Kontext ermitteln können. Die evtl. vorhandenen konstanten Vorgaben (z.B. Auftragsart) können später im Skript ergänzt werden. Für Testfälle können auch diese Informationen aus vorbelegten Eingabefeldern stammen.

6.1 Applikation erstellen

Erstellen Sie eine neue Applikation auf Basis der Applikationsvorlage Basisapplikation. Legen Sie auf der Eingabeseite die folgenden Eingabefelder an. Dabei sollte jeweils die Option



"Neues Datenfeld" gesetzt und jeweils der



im Folgenden angegebene Datentyp ausgewählt werden: Nach dem alle Eingabefelder angelegt sind, sieht die Eingabeseite ungefähr so aus:



Der Applikationstitel kann mit einem Doppelklick auf den Applikationsknoten in "SAP-Kundenauftrag mit Groovy anlegen" abgeändert werden.

6.2 Übersichtstabelle auf der Startseite

Auf der Startseite "Alle Einträge" können alle Elemente bis auf die Tabelle gelöscht werden.



Wählen Sie hier die folgenden Felder als Tabellenspalten aus:


Speichern Sie die Applikation und ordnen Sie sie in der Portal-Menüstruktur ein.

6.3. Die Applikation im Browser




Auf der Eingabeseite sehen Sie jetzt die angelegten Eingabefelder mit ihren Vorbelegungen. Tragen Sie Testdaten in die noch leeren, nicht schreibgeschützten Felder ein. Klicken Sie "OK".



Der neue Datensatz wird nun in der Tabelle auf der Startseite angezeigt.

6.4. Zusammenfassung

Die erstellte Applikation ermöglicht die Erfassung aller Daten, die für die Weiterverarbeitung in SAP benötigt werden. Aus Vereinfachungsgründen wurde die Erfassung von nur einer Auftrags-Position ermöglicht.

7. Prozess-Integration

Dieser Abschnitt enthält die eigentliche Anbindung eines SAP-Systems mit dem Ziel, per Prozess aus den eingegebenen Daten einen SAP-Kundenauftrag zu erzeugen. Der SAP-Kundenauftrag wird mit Groovy-Skript über einen SAP-Funktionsbaustein erzeugt.

7.1 Generieren des Groovy-Skripts

SAP-Funktionsbausteine können sehr komplexe Parameter anbieten. Um Fehler bei der Erstellung des Skripts zu vermeiden, wird mit Intrexx auch ein Skript-Generator ausgeliefert. Die komplette Beschreibung dazu finden Sie hier.

7.2. Prozess anlegen

Legen Sie im Modul Prozesse einen neuen Prozess an. Wählen Sie dabei als Ereignis, auf das reagiert werden soll, das " Ereignis durch Datensatzänderung" aus.



Klicken Sie "Weiter".



Wählen Sie hier die in diesem Teil des Entwicklerhandbuchs erstellte Applikation aus. Klicken Sie "Weiter".



Wählen Sie hier das Datensatzereignis "Einfügen" aus und klicken Sie "OK".

7.3. Groovy-Aktion

Wenn ein neuer Datensatz in der Applikation eingefügt wird, soll ein SAP-Kundenauftrag mit Groovy-Skript angelegt werden. Dazu wird jetzt eine Groovy-Aktion mit dem zuvor angelegten Datensatz-Ereignis verbunden.



Öffnen Sie den Eigenschaftendialog der Groovy-Aktion mit einem Doppelklick.



Klicken Sie "Weiter".



Öffnen Sie den Intrexx-Editor.



Hier kann das zuvor generierte Groovy-Skript eingefügt werden.

7.4. Felder aus der Datengruppe ermitteln

Das Skript wird jetzt angepasst.

Bitte beachten Sie, dass United Planet für Fehler, die aus nicht korrekten Anpassungen resultieren, keine Haftung übernimmt.

Zuerst müssen die Datenfelder aus der Intrexx-Applikation ermittelt werden.



Im Skript wird dazu ein Abschnitt eingefügt, in dem die Intrexx-Datenfelder referenziert werden. Mit der rechten Maustaste kann nach der Variablendefinition eine Liste der Datenfelder aus der Datengruppe eingeblendet werden, die Sie bei der Anlage der Groovy-Aktion verbundenen haben. Wird ein Datenfeld aus dieser Liste ausgewählt, so wird das entsprechende Skript an der Cursorposition eingefügt.



Hier das komplette Skript der Datenfeld-Referenzen:
//----------- get fields from intrexx application
String l_auart     = g_record["62DA58045C6CFD8563C3DEF0BAAE7C735D795DEA"].value /* datafield Auftragsart <string> */
String l_vkorg     = g_record["52F0E7D8EA1F753A9DDF0C1935CCAAA830A2366F"].value /* datafield Verkaufsorganisation <string> */
String l_vtweg     = g_record["FFAEE9A26755F1D3B97A8CA6BACE62CE7F9B323C"].value /* datafield Vertriebsweg <string> */
String l_spart     = g_record["C070F4974E8D089E39F161B42DD69F4F8BB8B5A1"].value /* datafield Sparte <string> */
String l_kunnr     = g_record["FD187855859411C25BE71F49712CA25BDDE35BB1"].value /* datafield Kundennummer <string> */
String l_bstnk     = g_record["23921A42F9BDF289B2C9525EB6B4136502E906D6"].value /* datafield Bestellnummer <string> */
String l_bstdt     = g_record["976D72ABB914AFACE9CFE6B8B68B3CC39FD21A4C"].value /* datafield Bestelldatum <datetime> */
String l_matnr     = g_record["370F41779D4901CB3A4291E618FD006AE1777581"].value /* datafield Artikel Nr. <string> */
String l_qunty     = g_record["F5FDA4922F324BA082A87A8BE2D6C169B59B9318"].value /* datafield Menge <integer> */

SAP-Parameter füllen

Die Datenfeld-Variablen müssen jetzt noch den richtigen Parametern des Funktionsbausteins zugeordnet werden. Im Skript sind die Parameter vorgeneriert. Den Parametern ist der leere Wert "l_value" zugeordnet. Beispiel:
g_sap.setImpStrucParField(l_function, "ORDER_HEADER_IN","DOC_TYPE", l_value); // ABAP Type C: 4,0
Diese sind jetzt zu ersetzen. Dazu ist "l_value" in diesem Beispiel durch die Variable "l_auart" zu ersetzen. Generiertes Coding für Tabellen kann wie folgt geändert werden:
// Imported Table ORDER_PARTNERS (ABAP Structure: BAPIPARNR) - Belegpartner
l_table = g_sap.getTable(l_function,"ORDER_PARTNERS");
for(int i = 0; i < 1; i++){
	l_table.appendRow();
	g_sap.setTableField(l_table, "PARTN_ROLE", "AG");  // ABAP Type C: 2,0
	g_sap.setTableField(l_table, "PARTN_NUMB", l_kunnr);  // ABAP Type C: 10,0
} // Table ORDER_PARTNERS end
Bei Tabellen wird generell eine FOR-Schleife erzeugt. Falls nur eine Tabellenzeile benötigt wird (wie hier im vereinfachten Beispiel) muss nur die 0 durch eine 1 ausgetauscht werden. Nicht benötigte Parameter können gelöscht werden, um das Skript klein und übersichtlich zu behalten. Falls sie später doch noch benötigt werden, können sie aus dem generierten Coding des SAP-Groovy Generators einzeln kopiert werden.

7.6. SAP-Aufruf auswerten

Im generierten Skript wird an dieser Stelle der SAP-Aufruf ausgeführt.
// Execute SAP function
if(g_sap.executeSapFunction(l_client, l_function)) {
if(l_trace) g_log.info(l_logprefix + "Fill export parameters")
// ---- get and check results
l_value = g_sap.getExpPar(l_function,"SALESDOCUMENT")	// ABAP Type: C 20,0 - Number of Generated Document
Das folgende Skript startet den SAP-Funktionsbaustein, wertet die zurück gegebene Auftragsnummer aus und schreibt diese in den aktuellen Datensatz in der Intrexx-Datengruppe. Im Fehlerfall wird ein Rollback ausgeführt.
//==========> EXECUTE SAP FUNCTION
if(g_sap.executeSapFunction(l_client, l_function)){
//  SALESDOCUMENT (ABAP Type: C 10,0) - Nummer des erzeugten Beleges
	String l_vbeln = g_sap.getExpPar(l_function,"SALESDOCUMENT");
	if(l_vbeln.equals("")){
		g_sap.BapiRollback(l_client);
		return null;
	}
//  save vbeln to datagroup
	l_conn = g_dbConnections.systemConnection;
	l_lid = g_record["66B1F38BA125C4C22444D27AC9108B91A208EE16"].getValue(); // datafield (PK) (S) ID
	l_stmtOrderUpdate = g_dbQuery.prepare(l_conn, "UPDATE XTABLE9EB02DDB SET SAP_VBELN = ? WHERE LID = ?");
	l_stmtOrderUpdate.setString(1, l_vbeln);
	l_stmtOrderUpdate.setInt(2, l_lid);
	l_stmtOrderUpdate.executeUpdate();
//  final commit
	g_sap.BapiCommit(l_client, false); // set to true if commit should wait
}else{
	g_sap.BapiRollback(l_client);
	return null;
};
Zur Fehlersuche eignet sich noch das folgende Coding, um die Meldungen der BAPIRET2-Nachrichten in die Logdatei zu schreiben.
// output bapi return messages
if(!l_function.getTableParameterList().getTable("RETURN").isEmpty()){
   l_function.getTableParameterList().getTable("RETURN").firstRow();
      for(int i = 0; i < l_function.getTableParameterList().getTable("RETURN").getNumRows(); i++){
         if(l_function.getTableParameterList().getTable("RETURN").getString("TYPE").equals("E")){
	g_log.error(l_function.getTableParameterList().getTable("RETURN").getString("MESSAGE"));
         }else{
	g_log.info(l_function.getTableParameterList().getTable("RETURN").getString("MESSAGE"));
         }
	l_function.getTableParameterList().getTable("RETURN").nextRow();
   }
}
Im Fehlerfall sind die Ausgaben aus den BAPI-Nachrichten in der Logdatei des Portals. Die Logdatei erreichen Sie im Modul Prozesse über das Hauptmenü Prozess / Logdatei analysieren. Nachdem das Skript komplett ist, kann der gesamte Prozess veröffentlicht werden.

8. Test

8.1. Neuen Datensatz erzeugen

In der zuvor erstellten Applikation SAP-Kundenauftrag mit Groovy anlegen kann nun ein Test-Datensatz erfasst werden. Die Auftragsnummer ist dabei schreibgeschützt und enthält noch keinen Wert. Mit Klick auf "OK" wird der Datensatz eingefügt und damit auch der Prozess mit der Groovy-Aktion ausgelöst.



Der soeben angelegte Datensatz ist nun mit der SAP-Auftragsnummer angereichert. Im Fehlerfall oder wenn die Auftragsnummer nicht eingetragen ist, sollte die Logdatei ausgewertet werden.

8.2. SAP-Auftrag anzeigen

Mit der SAP-Auftragsnummer kann der entsprechende Auftrag in SAP mit Transaktion "VA03" angezeigt werden.



8.3. Prüfen der Vollständigkeit

Nun muss von der Fachabteilung geprüft und bestätigt werden, ob der Auftrag in SAP identisch mit dem in der Intrexx-Applikation angelegten Datensatz ist. Außerdem müssen auch Folgeprozesse wie z.B. Lieferung oder Faktura geprüft werden.

9. Mögliche Erweiterungen

9.1. RFC Funktionen mit Positionsdaten

Im unserem Beispiel wurde bewusst auf die Verarbeitung von mehreren Positionen verzichtet. Das ist in vielen Szenarien praxisfern. Deshalb behandelt dieser Abschnitt die notwendigen Schritte, wenn mehrere Positionen mit Groovy-Skript verarbeitet werden sollen. Dazu kann die Datengruppe, die die Daten des Auftragkopfes speichert, als Elterndatengruppe gesehen werden. Unterhalb dieser Elterndatengruppe können Kinddatengruppen, so genannte untergeordnete Datengruppen verwendet werden, die die Positionen zu den Kopfdatensätzen beinhalten. Die Kinddatengruppe enthält dann die ID des Elterndatensatzes im Datenfeld "FKLID".



Hier sehen Sie eine stark vereinfachte Versandabwicklung. Die Datengruppe "Positionen" wurde als Unterdatengruppe zur Datengruppe "Versandbeleg" angelegt, die die Kopfdaten enthält. Nun könnte die Änderung eines Datensatzes aus der Datengruppe "Versandbeleg" das Groovy-Skript in einem entsprechenden Prozess auslösen. Dabei sollte allerdings geprüft werden, ob der Gesamtbeleg vollständig ist. Der Datensatz für den Versandbeleg wird in Intrexx gespeichert, noch bevor die erste Position erfasst ist. Der Prozess würde also von Intrexx aus ungefähr so aussehen:
  1. Kopfdaten in der Applikation erfassen und bestätigen
  2. Positionen in der Applikation erfassen
  3. Gesamtbeleg in der Applikation abschließen, z.B. mit einem manuell oder automatisch gesetzten Kontrollkästchen
  4. Weiterverarbeitung im Prozess mit Groovy-Aktion
// get db connection
def l_conn = g_dbConnections.systemConnection

// get Lid for parent record
def l_fkLid = g_record["BBCAC884A9397E98BD683B76386D58A39A8B56BC"].getValue(); // datafield (PK) (S) ID

// db query postions
def l_stmtPositions = g_dbQuery.prepare(l_conn, "SELECT LID, STR_BARCODEDERPOSITIO_616DDB16 FROM XDATAGROUP12A091EF WHERE FKLID = ?")
l_stmtPositions.setInt(1, l_fkLid)
def l_rsPositions = l_stmtPositions.executeQuery()

// loop all positions
l_rsPositions.each
{
	g_log.info("Record: " + it.value(1) + " = " + it.value(2))
}
Für das Groovy-Skript müssen die tatsächlichen technischen Namen der Datengruppe "Positionen" und des Datenfeldes "Barcode" auf dem Reiter Applikationsstruktur ermittelt und die Namen aus dem Beispiel-Skript damit ersetzt werden. Das Skript gibt die Informationen der Positionen in der Logdatei aus. Dort sind nach der Erfassung eines vollständigen Datensatzes mit Positionen die folgenden Informationen verfügbar.

INFO  2008-08-24 14:31:59,203 - de.uplanet.lucy.server.workflow.GroovySkriptCall[WebConnectorWorker-localhost:8102-8]
Record: 34 = 1000
INFO  2008-08-24 14:31:59,203 - de.uplanet.lucy.server.workflow.GroovySkriptCall[WebConnectorWorker-localhost:8102-8]
Record: 35 = 2000
Wenn die Positionsdaten wie im vorhergehenden Beispiel in die Tabellen eines SAP-Funktionsbausteines eingetragen werden sollen, so muss das Skript für den Loop nur minimal angepasst werden.
// loop all positions
l_table = g_sap.getTable(l_function,"IT_POSITION");
l_rsPositions.each
{
	l_table.appendRow();
	String l_barcode = it.value(2);
	g_sap.setTableField(l_table, "BARCODE", l_barcode);
}

9.2. Verwenden der Groovy-API in Velocity

Die Methoden der Groovy-API sind in der Businesslogik des Connectors für SAP Business Suite als Java-Klasse "net.initall.ixapi.groovy.IxSapGroovyAPI" implementiert. Die verfügbaren Methoden finden Sie im Anhang. Um die Methoden auch in Velocity nutzen zu können, muss die Groovy-API als "Callable" registriert sein. Callables sind ein Erweiterungskonzept für die Integration von beliebigen Java-Klassen. Die Registrierung solcher Java-Klassen erfolgt in der Portalkonfigurationsdatei "customcallables.cfg". Für die Nutzung der Groovy-API des Connectors für SAP Business Suite sollten Sie den Kontextnamen "GSAP" verwenden.
<?xml version="1.0" encoding="UTF-8"?>
<callables
	xmlns="urn:schemas-unitedplanet-de:lucy:server:velocity:callables"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="urn:schemas-unitedplanet-de:lucy:server:velocity:callables callables.xsd">
  <item contextName="GSAP" className="net.initall.ixapi.groovy.IxSapGroovyAPI" use="instance"/>
</callables>
Ab einer Busines Logik 2010 wird eine Schnellkonfiguration angeboten, die diese Einstellungen automatisch übernehmen.

9.3. Verwendung der simpleRFC-Funktionalität

Die simpleRFC-API stellt Funktionen zum Aufruf von BAPI/RFC-Funktionen in Velocity-Skript zur Verfügung. Velocity-Skripts können z.B. in Intrexx-Ansichtseiten eingebunden sein. Zu beachten ist, dass Velocity-Skript während der Generierung der ausgelieferten HTML-Seiten auf dem Server ausgeführt werden. Parameter müssen über Requestwerte oder über die Session übergeben werden. Es wird mindestens die Lizenz "View & Write" benötigt. Mit der Lizenz "View Only" lässt sich allerdings ein einfacher Aufruf verwenden, der einen simplen remotefähigen Funktionsbaustein mit einem Import- und Export-Parameter aufrufen kann. Die vollständige API ist im Anhang beschrieben. Hinweise für die Verwendung geben die folgenden Abschnitte.

9.3.1. Verwendung der Triggerfunktionalität (einfacher Aufruf)

Für einfache Aufrufe von RFC-Funktionen steht eine besondere Funktion der simpleRFC-API zur Verfügung. Diese kann z.B. für typische Trigger wie die Berechnung aktueller Daten in SAP u.ä. verwendet werden. Damit kann ein Import-Parameter vom Typ String gefüllt und ein Export-Parameter abgefragt werden.Die RFC-Funktionen setzen eine besondere Schnittstelle voraus:
function z_demo_trigger_simplerfc .
*"----------------------------------------------------------------------
*"*"Lokale Schnittstelle:
*"  IMPORTING
*"     VALUE(INPUT) TYPE  STRING OPTIONAL
*"  EXPORTING
*"     VALUE(RESULT) TYPE  STRING
*"----------------------------------------------------------------------

concatenate 'Antwort aus dem SAP. Eingabewert war:'
            input
            into result separated by ' '.

endfunction.
Als Import-Parameter wird der Parameter "INPUT" mit einem zeichenartigen Datentyp (z.B. String) erwartet. Falls ein Ergebnis zurück geschrieben werden soll, muss dies über den Export-Parameter "RESULT" erfolgen. Dieser Funktionsbaustein lässt sich dann aus einer Ansichtsseite starten, in dem ein Statischer Text mit der Option "Programmierung, Nur Standardsprache" angelegt ist. Der Aufruf wird über die simpleRFC-API als Programmtext angegeben:
$GSAP.simpleRfcTrigger("saperp", "system", "Z_DEMO_TRIGGER_SIMPLERFC", "externer Wert") 


Das Laden der Ansichtseite ruft nun immer den Funktionsbaustein auf und zeigt das Ergebnis des Export-Parameters "RESULT" als Text an. Im Intrexx ist es möglich, mit Javascript auf den angezeigten Wert des Statischen Textfeldes zuzugreifen (Attribute *.textContent). Durch das Einbinden von Requestwerten kann im Velocity-Skript eine bedingte Ausführung implementiert werden.
#set($command = $!Request.get("rq_command"))
#if($command == "trigger")
$GSAP.simpleRfcTrigger("saperp", "system", "Z_DEMO_TRIGGER_SIMPLERFC", "externer Wert") 
#end
Dieser einfache Aufruf von BAPI/RFC-Funktionen steht in der Lizenz "View Only" zur Verfügung.

9.3.2. Verwendung der kompletten simpleRFC-API

Das folgende Beispiel zeigt die Verwendung der simpleRFC-API in Ansichtsseiten für komplexere Funktionsbausteine. Die verfügbaren API-Funktionen finden Sie im Anhang. Die meisten API-Methoden haben als Ergebnis den Typ "boolean". Damit zeigt der SAP-Adapter an, ob der letzte Aufruf einer API-Methode erfolgreich war oder nicht. Das Fehlerhandling muss im eigenen Velocity-Skript erfolgen. Ein typisches simpleRFC-Skript hat den folgenden Aufbau: Als Beispiel wird hier eine einfache Funktion verwendet, die den Bestand von Werbegeschenken in der Exporttabelle "ET_STOCK" zur Verfügung stellt. Diese Tabelle muss entsprechend gefüllt werden:
function /iatl/messe_iphone_get_stock.
*"----------------------------------------------------------------------
*"*"Lokale Schnittstelle:
*"  TABLES
*"      ET_STOCK STRUCTURE  /IATL/MESSE_STOCK_INFO
*"----------------------------------------------------------------------

  define append_line.
    et_stock-matnr = &1.
    et_stock-maktx = &2.
    et_stock-count = &3.
    append et_stock.
  end-of-definition.

  append_line 'GA0001' 'Pfefferminze UP Design' 500.
  append_line 'GA0002' 'Geduldsspiel'           500.
  append_line 'GA0003' 'Porsche UP Design'      20.
  append_line 'GA0004' 'Skateboard UP Design'   100.
  append_line 'GA0005' 'Intrexx 4.5 10 User' 10.

endfunction.
Die Exportstruktur hat einen einfachen Aufbau und enthält den Materialnummer, Materialkurztext und den Bestand als Integerwert.



Diese SAP-Funktion wird in einer Ansichtsseite verwendet.



Im Element Statischer Text wird das Skript für den Aufrufdes SAP-Funktionsbausteins über die simpleRFC-API eingetragen. Das Ergebnis ist eine HTML-Ausgabe der zurückgegebenen Tabelle. Diese wird dem Requestparameter "sapstock" übergeben. Dieses erste Textfeld kann auch in den Versteckten Bereich verschoben werden. Ein zweites statisches Textfeld zeigt dann den aktuellen Requestwert und damit auch die aktuell ermittelte HTML-Ausgabe des Bestands als Text an. Das Skript des ersten statischen Textfeldes zeigt exemplarisch die Verwendung der simpleRFC-API-Methoden:
## open connection
Open Connecttion: $GSAP.simpleRfcConnect("saperp","system")

## function open
<br>Load Function: $GSAP.simpleRfcFunctionLoad("/IATL/MESSE_IPHONE_GET_STOCK")

## execute without commit
<br>Execute: $GSAP.simpleRfcFunctionExecute(false)

## loop export table
<br>Set Focus Table: $GSAP.simpleRfcSetFocusTable("ET_STOCK")
<br>Records found: $GSAP.simpleRfcTableGetCount()
#set($strOutput = "<table>")
#foreach($line in $GSAP.simpleRfcTableGetEntries())
 <br> List Item: $line
  Set Table Line: $GSAP.simpleRfcTableSetLine($line)	

#if($GSAP.simpleRfcSetFocusTableField("MATNR"))
#set($strMatnr = $GSAP.simpleRfcGetParameterValue())
#end

#if($GSAP.simpleRfcSetFocusTableField("MAKTX"))
#set($strText = $GSAP.simpleRfcGetParameterValue())
#end

#if($GSAP.simpleRfcSetFocusTableField("COUNT"))
#set($strCount = $GSAP.simpleRfcGetParameterValue())
#end

#set($strOutput = $strOutput + "<tr><td>" + $strMatnr + "</td><td>" + $strText + "</td><td>" + $strCount + "</td></tr>")
	
#end
#set($strOutput = $strOutput + "</table>")

## function close
<br>Close Function: $GSAP.simpleRfcFunctionClose(false)

## close Connection
<br>Close Connection: $GSAP.simpleRfcClose()

## set output
$strOutput
$Request.put("sapstock",$strOutput)

Besonders das Füllen und Auslesen von Parametern der Funktionbausteinschnittstelle kann hier aufwendig sein. Jeder Parameter muss erst fokussiert werden bevor er ausgelesen bzw. gesetzt werden kann. Strukturen und Tabellen erfordern eine doppelte Fokussierung - erst wird die Tabelle bzw. Struktur in den Fokus genommen, dann die Spalte (das Feld). Die simpleRFC-API erlaubt den Zugriff auf Tabellen über spezielle API-Methoden, z.B. zum Ermitteln der Anzahl, zum Positionieren oder zum Hinzufügen neuer Zeilen. In Kurzform bewirkt das folgende VM-Coding das Loopen über alle verfügbaren Tabellenzeilen:
$GSAP.simpleRfcSetFocusTable("ET_STOCK")
$GSAP.simpleRfcTableGetCount()
#foreach($line in $GSAP.simpleRfcTableGetEntries())
	$GSAP.simpleRfcTableSetLine($line)
	#if($GSAP.simpleRfcSetFocusTableField("MATNR"))
		#set($strMatnr = $GSAP.simpleRfcGetParameterValue())
	#end
	...	
#end

10. Weitere Informationen

Entwicklerhandbuch Teil 4
API Entwicklerhandbuch