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

Weitere Informationen
Entwicklerhandbuch Teil 4
API Entwicklerhandbuch

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 Business-Logik 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 Xtreme 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