ERP Integration Guidelines



Kurzer Überblick

Stellen Sie sich folgende Situation vor: Sie möchten die Anwendungen von der Coresystems-Umgebung nutzen, haben jedoch keine Verbindungsmöglichkeit, um Daten zwischen Ihrem System und Coresystems Cloud zu synchronisieren.

Keine Sorge! Diese Situation haben wir bedacht. Über die Data API 4 können Sie einen Konnektor erstellen, der Daten zwischen Ihrem System und Coresystems Cloud verbindet. Auf diese Weise können Sie Daten auf die Cloud hochladen und schließlich auf die Handys Ihrer Außendienstmitarbeiter übertragen.

Ein Konnektor kann auch verwendet werden, um alle Daten zu speichern, die von Außendienstmitarbeitern über die Client-Anwendungen von Coresystems zu Ihren externen Systemen hinzugefügt werden.

Der restliche Teil dieses Dokuments richtet sich an Software-Entwickler, die Data API 4 zur Erstellung eines Konnektors zwischen ihrem Datenverwaltungssystem und Coresystems Cloud verwenden möchten.



Im nächsten Abschnitt erstellen wir einen Anwendungsfall und schauen uns an Beispielanfragen an, wie wir Synchronisierungen über einen Konnektor duchführen können.

Um die API für Ihr Unternehmen nutzen zu können, müssen Sie Ihr Konto einrichten, das zu verwendende Datenmodell kennen und die Datenmapping-Methode herausfinden. Da die Data API 4 eine RESTful API ist, werden wir hier die Bezeichnung „Ressource“ für einen Objekttyp/ein Geschäftsobjekt verwenden.

Da sich ein Hilfsmittel meist am leichtesten in der Praxis erklären lässt, empfehlen wir Ihnen, ein Testkonto zu erstellen. (Wählen Sie die alleinstehende Unternehmensart und merken Sie sich den Unternehmensnamen, den Sie angeben.) So können Sie die Anweisungen in dieser Anleitung selbst durchspielen. Wenn Sie bereits ein Testkonto erstellt haben, haben Sie Zugang zu einem alleinstehenden Unternehmen mit veranschaulichenden Daten.

Nutzer für den Konnektor

Es empfiehlt sich, einen Nutzer zu verwenden, der allein für den Konnektor da ist, und die Berechtigungen für die Vorgänge Erstellen, Lesen, Aktualisieren und Löschen bei allen zu synchronisierenden Ressourcen für ALLE zu erteilen. So können Sie als Konnektor-Nutzer alle Vorgänge durchführen, die bei den Ressourcen erforderlich sind, und leichter Änderungen erkennen, die von anderen Nutzern oder dem Konnektor selbst vorgenommen wurden.


Der Anwendungsfall

Nehmen wir einmal an, Ihr Unternehmen verwendet SuperERP und Sie möchten einige Ihrer Datenmodelle mit der Coresystems-Umgebung integrieren, um Ihren Außendienstmitarbeitern mehr Mobilität und Informationen zu bieten.

Wir werden einige Geschäftspartner und Serviceabrufe synchronisieren müssen, damit Ihre Techniker wissen, was sie beim Einsatz erwartet.


Ressourcen erstellen

Senden wir zunächst einige Daten an Coresystems. Wir laden zwei Geschäftspartner (kurz: GP) und einen Serviceabruf (kurz: SA) hoch.

Die Data API ist eine RESTful API, d.h. alle Vorgänge sind an Ressourcen gebunden. Da dies viele Abrufe erfordern würde, um eine komplette Synchronisierungen durchzuführen, haben wir eine Batch API, über die Sie mehrere Abrufe in einer Anfrage senden können. Der Abruf würde wie folgt aussehen:

Anfrage für Objekte erstellen – Beispiel

Antwort für Objekte erstellen – Beispiel

TIPP: Falls Sie den Namen Ihres Unternehmens vergessen haben, können Sie diesen oben links einsehen, wenn Sie sich bei my.coresuite.com anmelden. Außerdem können Sie hier erfahren, wie Sie Ihre Basis-URL ermitteln können.

Verwendete DTO-Version

Sie müssen DTO-Versionen Ihrer Ressource verwenden, die SyncObject_V10 erweitern. Diese Version der DTOs enthält einige Felder, die für Konnektoren erforderlich sind (z.B. externalId und lastChangedBy).

Wie Sie sehen können, haben wir die externalId angegeben, die wir für diese Objekte verwenden möchten. Dies ist wichtig, da Sie nur mit diesen externen IDs arbeiten können, ohne ein Datenmapping zwischen dem Cloud-Identifikator und Ihren SuperERP-Identifikatoren speichern zu müssen.

Ein weiterer Vorteil besteht darin, dass Sie einen Bezug zu anderen Ressourcen über deren externalId herstellen können. Dies müssten Sie im Serviceabruf-Beispiel gut erkennen können.

Bitte beachten Sie, dass bei Batch-Prozessen alle Anfragen hintereinander entsprechend der gesendeten Reihenfolge verarbeitet werden und dass sie standardmäßig wie in einer großen Übertragung betrachtet werden. Wenn beispielsweise der Service nicht gespeichert werden kann, werden alle vorgenommenen Änderungen rückgängig gemacht.

Anfrage für Objekte erstellen – Fehlerbeispiel

Antwort für Objekte erstellen – Fehlerbeispiel

Wie Sie sehen können, ist ein Fehler beim Serviceabruf aufgetreten, denn der bezugnehmende Geschäftspartner existiert nicht. Folglich wurden keinerlei Daten gespeichert. Bevor Sie Daten erfolgreich auf die Cloud hochladen können, müssen Sie sicherstellen, dass Ihre Verweise gültig sind. Auf diese Weise können wir die Daten abgleichen und die Verantwortungen des Konnektors klar definieren.

Sie können schnell erkennen, dass der Geschäftspartner nicht gespeichert wurde, indem Sie wie folgt einen GET-Abruf über die externalId durchführen:

Einfacher GET-Abruf über externalId

GET https://{baseUrl}/api/data/v4/BusinessPartner/externalId/GPExtId3?clientIdentifier=COR_CON_NONE&accountName=eid4&userAccountName=user4&userAccountPassword={userAccountPassword}&companyName=SmartMove&dtos=BusinessPartner.20

Es könnte jedoch vorkommen, dass Sie eine erste Synchronisierung durchführen möchten, bei der Sie alle Geschäftspartner synchronisieren und in der Cloud speichern. Hierfür könnten Sie einen Batch Call verwenden und den Parameter transactional = false umgehen. So können wir alles speichern, was möglich ist, und Ihnen eine gesonderte Antwort auf einzelne Anfragen geben, damit Sie herausfinden können, welche Daten nicht erfolgreich übertragen wurden.

Nicht-transaktionelle Objekte mit Fehlern erstellen

Nicht-transaktionelle Objekte mit Fehlerantwort erstellen

In diesem Fall wurde der erste Geschäftspartner erstellt und in der Cloud gespeichert, wohingegen der zweite nicht erstellt oder gespeichert wurde.


Transaktional oder nicht-transaktional

Wir empfehlen, die Batch-Anfrage als große Übertragung zu belassen, wenn Sie Upstream-Daten senden, die in Abhängigkeit zueinander stehen. Nicht-transaktionale Batch-Anfragen sollten nur verwendet werden, wenn die Einheitlichkeit der Daten zweitrangig ist und möglichst viele Objekte in Coresystems verfügbar sein sollen.

Nun haben wir einige Daten in der Cloud. Nutzen Sie Ihre iOS- oder Android-App oder gehen Sie direkt zu my.Coresuite.com und durchsuchen Sie Ihre Daten. Nutzen Sie bei der Anmeldung in den Anwendungen die Zugangsdaten eines anderen Nutzers, um eine realistische Situation nachzustellen. Ich habe zum Beispiel user4 für den Konnektor und user5 für my.coresuite.com verwendet.


Erstellte oder bearbeitete Ressourcen in einem festgelegten Zeitrahmen abrufen

Nehmen wir an, der Außendienstmitarbeiter (user5) erstellt einen neuen Serviceabruf. Sie möchten die Änderungen sehen und speichern sie in SuperERP.

Unsere aktuelle API-Version unterstützt nur Intervall-Synchronisierungen. D.h., um bearbeitete Daten zu erhalten, müssen Sie bearbeitete Objekte in einem festgelegten Zeitrahmen anfragen. Derzeit unterstützen wir keine Synchronisierung mit Benachrichtigungen, bei der Sie sich für Aktualisierungen registrieren können und die Sie bei einer Änderung erhalten würden. Sie müssen die Coresystems Cloud in regelmäßigen Abständen abfragen, um bearbeitete Daten abzurufen.

Wie funktioniert der Vorgang? Folgender Abruf wird alle erstellten und bearbeiteten Serviceabrufe zurückgeben.

Geänderte Serviceabrufe der letzten 10 Minuten abrufen

GET https://{baseUrl}/api/data/v4/ServiceCall?useExternalIds=true&pageSize=400&query=(lastChangedBy!=me()) AND (lastChanged >= 1459257408135) AND (lastChanged < 1459258008111)
&clientIdentifier=COR_CON_NONE&accountName=eid4&userAccountName=user4&userAccountPassword={userAccountPassword}&companyName=SmartMove&dtos=ServiceCall.19

Antwort mit zuletzt geänderten Serviceabrufen

In diesem Beispiel wird der Anfrage-Parameter verwendet, um auszudrücken, dass Sie die Objekte möchten, die von anderen Nutzern in letzter Minute geändert wurden. Außerdem erhalten Sie zur leichteren Erkennbarkeit in Ihrem System über useExternalIds = true die Verweise, die mit der externalId verbunden sind.

Sie müssen in der Anfrage zudem das Zeitintervall angeben, da Sie die Daten über das Feld lastChanged anfordern. Der Protokolleintrag, den Sie dort sehen werden, steht für die Anzahl der Millisekunden seit 1. Januar 1970, 00:00:00 Uhr GMT. (In Java entspricht dies dem Parameter Date.getTime().)

Wie bei der Antwort ersichtlich wird, können Sie auch die externalId des Geschäftspartners finden und den Verweis im SuperERP-System lösen. Im Feld der externalId für diesen Serviceabruf wird zunächst „null“ stehen. Ersetzen Sie diesen Wert.


Neue Daten von der Coresystems Cloud

Wenn die externalId der Ressource „null“ ist, nachdem Sie neue oder bearbeitete Daten von der Coresystems Cloud abgerufen haben, müssen Sie die externalId in der Cloud aktualisieren. Vorher müssen Sie diese in Ihrem externen System speichern. Auf diese Weise können Sie die Einheitlichkeit der Daten gewährleisten.

Nachteile von Cloud-Transaktionen

Nehmen wir an, ein Techniker arbeitet eine Woche lang sehr viel auswärts und synchronisiert nach dieser Woche alle Daten mit der Cloud. Dieser Vorgang könnte 5-10 Minuten dauern. Was passiert dabei in der Cloud?

Die Cloud beginnt die Übertragung um 15:00 Uhr, erstellt die Objekte und beendet die Transaktion um 15:05 Uhr erfolgreich. Danach sind alle Daten abgeschickt. In der Cloud werden neue Objekte angezeigt, die dort vor 5 Minuten erstellt wurden. Das Feld LastChanged zeigt den Zeitwert vom Beginn der Übertragung, d.h. 15:00 Uhr.

Welche Auswirkungen hat dies auf Sie?

Bei einer regulären Synchronisierung hätten Sie vielleicht folgende Datenfolge:

t1: [0, t1], t2: (t1, t2], t3: (t2, t3], … wobei ti = ti-1 + 1 Minute. Das heißt, dass Sie bei t1 alle Daten ab dem Anfang bis zum t1-Moment erhalten, bei t2 alle Daten ab t1 bis t2, und so weiter und so fort.

Wenn Sie die obige Datenfolge nutzen, kann es vorkommen, dass Sie einige Objektaktualisierungen bei längeren Übertragungen wie dieser 5-minütigen Übertragung verlieren. Bei t3 würden Sie nicht sehen, dass Objekte zwischen dem Übertragungsintervall (t1,t2] und Intervall (t2,t3] gespeichert wurden, da diese Objekte als geänderte Objekte im Intervall (t1,t2] angezeigt werden würden.

Es gibt einige Möglichkeiten, um dies zu vermeiden:

1. Option: Nutzen Sie eine Datenfolge, bei der Daten miteinander verknüpft sind.

Die Folge würde folgendermaßen aussehen:

t1: [0, t1], t2: (t1 - C, t2], t3: (t2 - C, t3], ... wobei ti = ti-1 + 1 Minute und C eine Konstante ist, z. B. 5 Minuten.

Wenn Sie eine Synchronisierung bei t3 veranlassen und ein Objekt in einer Transaktion gespeichert wird, die im Intervall (t1,t2] begann und im Intervall (t2,t3] aufhörte, erhalten Sie diese Änderung.

Allerdings gibt es hier eine weitere Einschränkung. Sie werden in mehreren Synchronisieranfragen dieselbe Objektaktualisierung erhalten und Sie werden herausfinden müssen, ob Sie diese Objektaktualisierung bereits durchgeführt haben oder nicht.

Hierfür könnten Sie im Konnektor eine Verlaufstabelle nutzen, in der Sie die Werte externalId und cloud lastChanged speichern, oder einfach das Cloud-Objekt mit dem Objekt vom ERP-System vergleichen, um herauszufinden, ob Sie es verarbeiten müssen.

2. Option: Nutzen Sie eine Datenfolge, die völlig anders ist, aber nicht bis zum aktuellen Moment geht.

Die Folge würde folgendermaßen aussehen:

t1: [0, t1 - C], t2: (t1 - C, t2 - C], t3: (t2 - C, t3 - C], ... wobei ti = ti-1 + 2 Minute und C eine Konstante ist, z. B. 5 Minuten.

Jetzt erhalten Sie keine Doppeleinträge, haben allerdings auch nicht die aktuellsten Daten. Um 15:05 Uhr werden Sie lesen, dass die Daten auf der Cloud zwischen 14:58-15:00 Uhr geändert wurden.

Es ist Ihnen überlassen, welche Lösung Sie wählen oder ob Sie eine andere Lösung finden. Unterdessen arbeiten wir daran, die Einschränkung der Datenübertragung aufzuheben, damit die Synchronisierung normal und einfach vonstatten geht.


Ressourcen aktualisieren

Schauen wir nun, wie wir dieses neu erstellte Objekt auf der Cloud aktualisieren können, um die externalId hinzuzufügen. Bei diesem Beispiel müssen wir den Cloud-Identifikator nehmen, weil wir der Coresystems Cloud sagen möchten, dass sie ihr Objekt mit unserem Objekt verknüpfen soll. Um dies zu tun, können wir folgenden Abruf durchführen:

Cloud-Objekt mit externalId aktualisieren

PATCH https://{baseUrl}/api/data/v4/ServiceCall/718ABEFA623D4422AEB01912801903C5?forceUpdate=true
&clientIdentifier=COR_CON_NONE&accountName=eid4&userAccountName=user4&userAccountPassword={userAccountPassword}&companyName=SmartMove&dtos=ServiceCall.19 HTTP/1.1
{
   "externalId": "ScUpdatedExtId"
}

Wir empfehlen die PATCH-Methode. So können Sie nur die Daten weitergeben, die Sie ersetzen möchten. Die Coresystems Cloud verbindet dann die Ressource, die über die angegebene ID identifiziert wird, mit den Informationen, die Sie angegeben haben.

Bei dieser Anfrage gibt es einen weiteren Trick. Die Markierung forceUpdate = true zeigt an, dass die Ressource mit dieser externalId aktualisiert werden soll, ganz gleich ob sie geändert wurde oder nicht. So überspringen Sie im Prinzip den Mechanismus, der gleichzeitige Änderungen überprüft.

Sie können entscheiden, ob überprüft werden soll, dass ein Objekt seit den Änderungen bearbeitet wurde oder nicht. Falls ja, müssen Sie das Feld lastChanged mit demselben Wert übertragen, den Sie von der Cloud für dieses Objekt erhalten haben, und die Markierung forceUpdate nicht mehr verwenden. Die Anfrage sieht dann wie folgt aus:

Cloud-Objekt mit externalId aktualisieren

PATCH https://{baseUrl}/api/data/v4/ServiceCall/718ABEFA623D4422AEB01912801903C5?clientIdentifier=COR_CON_NONE&accountName=eid4&userAccountName=user4&userAccountPassword={userAccountPassword}&companyName=SmartMove&dtos=ServiceCall.19 HTTP/1.1
{
   "externalId": "ScUpdatedExtId",
   "lastChanged" : 1459258008000
}

Falls es einen Fehler bei der gleichzeitigen Bearbeitung gibt, erhalten Sie ungefähr folgende Antwort:

Antwort bei gleichzeitiger Änderung

Status : 409 Conflict
{
   "error":"CA-27",
   "message":"Eine gleichzeitige Ressourcen-Bearbeitung wurde entdeckt. Datenbank-Ressource zuletzt geändert am: [{0}].",
   "values":[
      1459252975924
   ]
}

Wir haben bisher gelernt, wie neue Objekte von der Coresystems Cloud abgerufen und mit externen IDs aktualisiert werden können. Wir haben auch gelernt, wie neue Objekte in Coresystems Cloud mit externen IDs erstellt werden können. Jetzt bleibt die Frage: Wie lassen sich Objekte in Coresystems Cloud mit Daten von Ihrem System aktualisieren? Ein Kinderspiel! Erstellen Sie einfach ein PATCH über die externalId.

Cloud-Objekt über externalId aktualisieren

PATCH https://{baseUrl}/api/data/v4/ServiceCall/externalId/ScUpdatedExtId?clientIdentifier=COR_CON_NONE&accountName=eid4&userAccountName=user4&userAccountPassword={userAccountPassword}&companyName=SmartMove&dtos=ServiceCall.19 HTTP/1.1
{
   "statusName": "Closed",
   "statusCode" : "-1"
}

Gelöschte Objekte

Es gibt zwei Aspekte beim Umgang mit gelöschten Objekten. Zunächst einmal möchten Sie sicherlich:

Vorhandene Ressourcen löschen

Wenn beispielsweise ein Backoffice-Nutzer von SuperERP einen Geschäftspartner löscht, weil er schlecht zahlt, dann möchte er diesen Geschäftspartner sicherlich auch in der Coresystems Cloud löschen, damit dieser Geschäftspartner nach einer Datensynchronisierung von den Geräten der Außendienstmitarbeiter verschwindet. Wie lässt sich dies bewerkstelligen? Stellen Sie eine einfache Lösch-Anfrage über die externalId:

Über externalId löschen

DELETE https://{baseUrl}/api/data/v4/BusinessPartner/externalId/GPExtId2?forceDelete=true
&clientIdentifier=COR_CON_NONE&accountName=eid4&userAccountName=user4&userAccountPassword={userAccountPassword}&companyName=SmartMove HTTP/1.1

Dies wird den Geschäftspartner mit der externen ID „GPExtId2“ löschen. Wie Sie sehen können, haben wir zudem die Markierung forceDelete für Aktualisierungen verwendet. Dadurch umgehen wir den gleichzeitigen Bearbeitungsmechanismus. Sollten Sie diesen Mechanismus verwenden wollen, sollten Sie das Feld lastChanged wie folgt übertragen:

Über externalId löschen

DELETE https://{baseUrl}/api/data/v4/BusinessPartner/externalId/GPExtId2?lastChanged=1459167207776
&clientIdentifier=COR_CON_NONE&accountName=eid4&userAccountName=user4&userAccountPassword={userAccountPassword}&companyName=SmartMove HTTP/1.1

Gleichzeitige Bearbeitung über den Konnektor

Wir empfehlen, den Konnektor so zu entwickeln, dass er erzwungene Aktualisierungen und Löschvorgänge ausführt. So müssen Sie nicht die letzte Änderung von Coresystems und dem externalId-Mapping speichern.

Bitte beachten Sie unbedingt, dass beim Löschen eines Geschäftspartners all die Objekte, die zum gelöschten Geschäftspartner verweisen, weiterhin auf Coresystems Cloud verbleiben. Sie werden weiterhin die Serviceabrufe sehen, die mit dem Geschäftspartner GPExtId2 auf dem Gerät verbunden sind. Dieser Geschäftspartner wird jedoch nicht mehr für diese Serviceabrufe angezeigt. Falls Sie diese Serviceabrufe nicht mehr sehen möchten, ist es die Aufgabe des Konnektors, alle verbundenen Objekte von Coresystems zu löschen.

Gut. Jetzt haben wir also ein Objekt von der Coresystems Cloud gelöscht. Schauen wir uns nun an, wie wir gelöschte Objekte von der Coresystems Cloud abrufen können.

Gelöschte Ressourcen von einem bestimmten Zeitraum abrufen

Es könnte der Fall auftreten, dass ein Außendienstmitarbeiter einen Serviceabruf löscht und der Konnektor dies sehen muss, um den Eintrag aus dem SuperERP zu löschen.

Sie müssen dann gelöschte Daten mit externalIds im angegebenen Zeitraum abrufen. Hierfür müssen Sie einen ähnlichen Abruf stellen:

Gelöschte Objekte mit externalIds abrufen

GET https://{baseUrl}/api/data/v4/BusinessPartner/deleted?dtos=DeletedObjects.2&from=1440765076962&to=1442230064023
&clientIdentifier=COR_CON_NONE&accountName=eid4&userAccountName=user4&userAccountPassword={userAccountPassword}&companyName=SmartMove

Antwort mit gelöschtem Geschäftspartner mit externalIds

HTTP/1.1 200 OK

{
  "deletedIds": [
    {"id" : "CE037D0236CB49AF8D22EFB6DA1E9409", "externalId" : "GPExtId1"},
    {"id" : "AE037D0236CB49AF8D22EFB6DA1E9411", "externalId" : "GPExtId2"},
    {"id" : "WOW37D0236CB49AF8D22EFB6DA1E9420"} //in case this object has no externalId set.
  ]
}

Wie Sie sehen können, erhalten Sie eine Liste mit Identifikatoren, die den Cloud-Identifikator und die externe ID enthält. Sollte es keine externe ID geben, bedeutet dies, dass dieses Objekt nicht in Ihren Systemen gespeichert wurde.

Bei dieser Funktion gibt es allerdings eine Einschränkung, die wir schnellstmöglich in Angriff nehmen werden. Derzeit erhalten Sie in der Liste auch die Objekte, die vom Konnektor selbst gelöscht wurden. lastChangedBy != me() funktioniert bei diesen Anfragen nicht.


Schlussfolgerung

Wir sind nun die meisten Aufgaben eines Konnektors durchgegangen. Denken Sie daran, dass Sie mehrere Abrufe über die Batch API zusammenfassen können und Sie somit über einen einzigen Abruf einen Überblick über das gesamte Unternehmen erhalten können! Sie können auch die Daten filtern, die Sie von der Cloud erhalten, und weitere nützliche Anfragen über die Query API stellen. Über die Referenz der Coresystems API und Query API erfahren Sie, wie Sie den perfekten Konnektor für Ihr Unternehmen entwickeln können.