SAP Business One Import
Datenextraktion aus SAP Business One und Import in Bilendo: Schlüssel, Ausgleich, Aufträge und Delta-Läufe.
Diese Seite beschreibt, wie die Daten aus SAP Business One extrahiert, flach gemacht und an Bilendo übergeben werden. Sie gilt für beide Wege (Pull und Push, siehe die Seite SAP Business One Hub). Die Felder selbst stehen in der Architektur SAP Business One.
So werden die Daten extrahiert
Jeder SAP-Business-One-Mandant ist eine eigene Datenbank (SAP HANA oder Microsoft SQL Server) und wird getrennt extrahiert. Die Tabellen sind bereits relational; der bevorzugte Weg ist daher je Kategorie (Kunden, offene Posten, ausgeglichene Posten, optional offene, nicht gelieferte Aufträge) eine lesende SQL-Abfrage auf diese Datenbank. Ohne Datenbankzugriff liefert der Service Layer (OData: BusinessPartners, JournalEntries, Invoices, Orders) dieselben Fakten mit Paging und $filter; die DI API ist der Ausweg für On-Premise-Add-ons. Die Feldnamen sind die Tabellenfelder von B1; der Service Layer schreibt sie nur anders.
So werden sie flach gemacht
Jede Kategorie wird als EINE flache Tabelle geliefert (CSV oder SQL-Ergebnis), eine Zeile je Schlüssel, Spaltenkopf = Feldname, keine verschachtelten Strukturen. Offener Betrag und Ausgleichsdatum werden auf der SAP-Seite berechnet und als fertige Spalten geliefert; Bilendo rechnet sie nicht nach.
SAP Business One (eine Mandanten-Datenbank)
|
+- OCRD + CRD1 + OCPR -------------------------> 1) Kunden, eine Zeile je CardCode
| CardType = 'C', Rechnungsadresse, Kontakt
| Schluessel: CompanyCode + CardCode, einmal je Datei
|
+- JDT1 (nur Kundenzeilen, ueber OCRD)
| Schluessel: CompanyCode + TransId + Line_ID, aendert sich nie
| + OJDT Kopftext, Anlagedatum
| + OINV / ORIN Rechnungsnummer (TransType 13 / 14)
| + ITR1 + OITR Abstimmung (Ausgleich)
| |
| | OpenAmount = BalDueDeb - BalDueCred
| | ClearingDate = juengstes ReconDate, nur wenn OpenAmount = 0
| |
| +-- OpenAmount != 0 ---------------------> 2) offene Posten, Schluessel TransId + Line_ID
| |
| +-- OpenAmount = 0 und abgestimmt -------> 3) ausgeglichene Posten, gleiches Template
|
+- ORDR + RDR1 (optional) ---------------------> 4) offene, nicht gelieferte Auftraege, eine Zeile je Auftrag
Schluessel: CompanyCode + CardCode + DocNum
jede Lieferung = ALLE offenen Auftraege, kein Delta
1) bis 4) -> flache CSV / SQL-Ergebnis -> Bilendo-ImportKunden (Stammdaten): eine Zeile je
OCRD.CardCodemitCardType = 'C'undfrozenFor <> 'Y', dazu die konstante SpalteCompanyCode.CRD1überCardCodemitAdresType = 'B'undAddress = OCRD.BillToDef(die Standard-Rechnungsadresse; ohne eine die erste Rechnungsadresse) verknüpfen,OCPRüberCardCodeundName = OCRD.CntctPrsn(der Standard-Ansprechpartner). LEFT JOINs verwenden, damit ein Kunde ohne Adresse oder Kontakt in der Liste bleibt, und jeden Join auf EINE Zeile verdichten.Offene Posten (Bewegungsdaten): eine Zeile je Buchungszeile
JDT1(SchlüsselCompanyCode+TransId+Line_ID). INNER JOINOCRDüberShortName = CardCodebehält nur Kundenzeilen und lässt Sachkontenzeilen weg. LEFT JOINOJDTüberTransIdfür Kopftext und Anlagedatum, undOINV(bzw.ORIN) überCreatedBy = DocEntryUNDTransType13 (Rechnung) oder 14 (Gutschrift) für Rechnungsnummer, Zahlungsbedingung, Stornokennzeichen und Niederlassung. Ausgleich: LEFT JOINITR1überTransIdundTransRowId = Line_ID, dannOITRüberReconNum(nurCanceled = 'N'); eine Zeile mit mehreren Abstimmungen hat dort mehrere Einträge und wird auf einen verdichtet (jüngstesReconDate, dessenReconNum). Beide werden nur geliefert, wo der offene Betrag 0 ist (siehe Ausgeglichene Posten).Beträge: Belegbetrag =
Debit - Credit. Der offene Betrag kommt fertig berechnet als SpalteOpenAmount=BalDueDeb - BalDueCred(Hauswährung, Forderung positiv); er ist 0, sobald die Zeile ausgeglichen ist. Die Fremdwährung steht inFCCurrency(leer = Hauswährung des Mandanten). Gutschriften und Zahlungseingänge kommen mit umgekehrtem Vorzeichen und bleiben so.Aufträge (optional): die offenen, nicht gelieferten Aufträge, eine Zeile je Auftrag auf Kopfebene; der offene Betrag wird aus den
RDR1-Zeilen aufsummiert (siehe Offene, nicht gelieferte Aufträge).
Schlüssel und Doubletten
Bilendo bildet seine Schlüssel aus den gelieferten Spalten. Eine Doublette im debitorischen Nebenbuch führt zu falschen Salden; deshalb gelten die folgenden Regeln streng. Innerhalb EINES Batches (eines Lieferobjekts) erkennt Bilendo einen wiederholten Schlüssel als Doublette und nimmt ihn nicht an. Über getrennte Lieferungen hinweg überschreibt die neuere die Werte der älteren unter demselben Schlüssel (Kunden und Buchungen; Aufträge funktionieren anders, siehe unten).
Kunden-Schlüssel =
CompanyCode+CardCode. In einem Batch darf er nur EINMAL vorkommen.CompanyCodeist eine konstante Spalte (der Mandant als mit dem Kunden vereinbartes, nie geändertes Kürzel), weil SAP Business One keine solche Spalte kennt: jeder Mandant ist eine eigene Datenbank.Posten-Schlüssel =
CompanyCode+TransId+Line_ID. Er ändert sich über alle Lieferungen nie, auch nicht, wenn der Posten ausgeglichen wird: eine Rechnung über 1.000 Euro behält denselben Schlüssel, solange sie existiert, und jede Änderung daran kommt erneut MIT DEMSELBEN Schlüssel, damit die neueren Werte die älteren ersetzen. Innerhalb eines Batches ist der Schlüssel eindeutig; offene und ausgeglichene Posten eines Batches teilen nie einen Schlüssel.Auftrags-Schlüssel =
CompanyCode+CardCode+DocNum. Anders als Kunden und Buchungen wird ein Auftrag nicht unter seinem Schlüssel aktualisiert: siehe Offene, nicht gelieferte Aufträge.Ausgeglichen = derselbe Schlüssel: Wird ein Posten vollständig ausgeglichen (
OpenAmount = 0), kommt er erneut mit DEMSELBEN Schlüssel, jetzt mitOpenAmount = 0und einemClearingDate. Das ist eine Änderung des bestehenden Postens, nie ein neuer Posten.Reihenfolge der Lieferungen: Getrennte Lieferungen werden in der Reihenfolge angewendet, in der sie ankommen, die neuere überschreibt die ältere. In zeitlicher Reihenfolge senden; ein älterer Auszug, der nach einem neueren gesendet wird, würde die alten Werte zurückbringen.
Join-Fallen:
DocEntryist nur je Belegart eindeutig, deshalb werdenOINV/ORINüberDocEntryUNDTransTypeverknüpft. Jeder 1:n-Join (ITR1,CRD1,OCPR,RDR1) wird vor der Lieferung auf eine Zeile verdichtet. Die Extraktion prüft vor jedem Batch, dass die Zahl der Zeilen der Zahl der verschiedenen Schlüssel entspricht.Stornos: Ein stornierter Beleg erzeugt eine Gegenbuchung mit eigener
TransId, also einem neuen Schlüssel; die ursprüngliche Buchung behält ihren Schlüssel.
Ausgeglichene Posten
Ausgeglichene Posten nutzen DASSELBE Template wie die offenen Posten: dieselben Felder, dieselbe flache Tabelle und denselben Schlüssel (CompanyCode + TransId + Line_ID); nur die Auswahl ist anders. Sie kommen daher als zweiter Auszug (oder in derselben Datei, solange der Schlüssel eindeutig bleibt). Ein ausgeglichener Posten ist der spätere Zustand eines offenen Postens: Er kommt mit dem Schlüssel, den er schon hat.
Welche Zeilen: die Kundenzeilen von
JDT1(dieselben Joins wie bei den offenen Posten) mitOpenAmount = 0(BalDueDeb = 0undBalDueCred = 0), die eine Abstimmung tragen (ITR1/OITRmitCanceled = 'N').DebitundCreditbehalten den ursprünglichen Betrag; ein ausgeglichener Posten zeigt also weiter, was gebucht wurde, nur der offene Betrag ist 0.Wie eine Zeile ausgeglichen wird: In B1 verbindet eine Abstimmung (
OITR.ReconNum) Soll- und Habenzeilen eines Kunden, z. B. eine Rechnung (TransType13) mit dem Zahlungseingang (24) oder der Gutschrift (14), die sie ausgleicht. Beide Seiten tragen dieselbeReconNumund dasselbeReconDate; BEIDE Seiten gehören in den Auszug, so verknüpft Bilendo Rechnung und Zahlung.Ausgleichsfelder:
ClearingDate(das jüngsteOITR.ReconDateder Zeile) undReconNumsind NUR gefüllt, woOpenAmount = 0ist. Eine teilweise ausgeglichene Zeile bleibt offener Posten mit Saldo über 0 und hat KEIN Ausgleichsdatum; sonst bleiben beide leer.Zeitfenster: Der erste Lauf nimmt die ausgeglichenen Zeilen des vereinbarten Zeitraums nach
ClearingDate(meist die letzten 24 Monate); spätere Läufe nur die seit dem letzten Lauf ausgeglichenen Zeilen.
Offene, nicht gelieferte Aufträge
Aufträge (optional) sind ein Schnappschuss, kein Strom von Änderungen. Bilendo bildet den Auftrags-Schlüssel aus CompanyCode + CardCode + DocNum, und es wird nichts überschrieben: Mit jeder Lieferung archiviert Bilendo alle Auftragssätze, die es vorher erhalten hat, und legt die Sätze der neuen Lieferung neu an.
Welche Aufträge: nur offene, nicht gelieferte Aufträge:
ORDR.DocStatus = 'O', nicht storniert, mit mindestens einerRDR1-Zeile mitLineStatus = 'O'undOpenQty > 0. Ein teilweise gelieferter Auftrag bleibt drin, mit dem offenen Betrag des Rests.Immer vollständig: Jede Lieferung enthält ALLE offenen, nicht gelieferten Aufträge des Mandanten, nie nur die geänderten. Ein Auftrag, der in einer Lieferung fehlt, wird von ihr archiviert; ein Teilauszug würde also Aufträge archivieren, die noch offen sind.
Geliefert oder geschlossen = weg: Ein vollständig gelieferter, geschlossener oder stornierter Auftrag ist in der nächsten Lieferung einfach nicht mehr enthalten und wird dort archiviert. Es braucht keine Statusänderung und keine Löschzeile.
Eine Zeile je Auftrag: Kopfebene; der offene Betrag wird aus den Zeilen aufsummiert (
OpenOrderAmountin Hauswährung,OpenOrderAmountFCin Belegwährung). Der Schlüssel ist innerhalb eines Batches eindeutig, wie in jeder Kategorie.Reihenfolge der Lieferungen: Es zählt die neueste Lieferung. In zeitlicher Reihenfolge senden; ein älterer Schnappschuss, der nach einem neueren gesendet wird, würde die neueren Aufträge archivieren und die alten zurückbringen.
Delta-Läufe
Kunden (Stammdaten): Der erste Lauf liefert alle Kunden. Spätere Läufe liefern neue Kunden (OCRD.CreateDate) und geänderte Kunden (OCRD.UpdateDate), einen Tag zurück, jeweils unter demselben Schlüssel (CompanyCode + CardCode), damit die neueren Werte die älteren ersetzen. Eine Änderung an Rechnungsadresse oder Ansprechpartner gehört zum Kunden: An der Instanz des Kunden bestätigen, dass eine solche Änderung OCRD.UpdateDate verschiebt; tut sie das nicht, werden in jedem Lauf alle Kunden geliefert, was die Schlüsselregeln sicher machen. Empfohlen: die Kunden eines Laufs vor dessen Buchungen senden, damit eine Buchung nie auf einen Kunden zeigt, den Bilendo noch nicht kennt.
Buchungen (Bewegungsdaten): Neue Buchungen findet man über OJDT.CreateDate (einen Tag zurück neu lesen); eine Änderung an einer bestehenden Buchung (OJDT.UpdateDate) kommt erneut mit demselben Schlüssel. Ein offener Betrag ändert sich auch, wenn eine Zeile ausgeglichen wird, ohne neue Buchung: jede Zeile mit offenem Saldo neu lesen, dazu die seit dem letzten Lauf ausgeglichenen Zeilen (OITR.ReconDate). Eine stornierte Abstimmung (Canceled = 'Y') setzt die Zeile wieder auf offen: sie kommt mit dem erneuten Lesen der offenen Posten unter demselben Schlüssel zurück, mit OpenAmount über 0 und ohne Ausgleichsdatum, und fällt aus den ausgeglichenen Posten heraus.
Aufträge: kein Delta. Jeder Lauf liefert den vollständigen Schnappschuss der offenen, nicht gelieferten Aufträge.
Bitte an Ihrem System prüfen
Die Tabellen- und Feldnamen folgen dem SAP-Business-One-Standardschema. Angepasste Installationen (benutzerdefinierte Felder, Add-ons, eine andere B1-Version) können abweichen: Lassen Sie Joins und Feldnamen vor der ersten Extraktion mit Ihrem SAP-Partner an Ihrer eigenen Instanz bestätigen. Der Rückblick-Zeitraum für ausgeglichene Posten wird je Kunde vereinbart. Mahnstufe und Mahnstopp haben in B1 kein Standardfeld und gehören deshalb nicht zu dieser Seite; führen Sie sie in einem benutzerdefinierten Feld, nehmen wir es als Custom Field auf. Zwei Fälle würden einen Schlüssel ändern und müssen vor der ersten Extraktion mit dem Kunden geklärt werden: Manuelle Buchungen (TransType 30) lassen sich in SAP Business One nachträglich ändern, und wenn Zeilen eingefügt oder entfernt werden, kann sich Line_ID verschieben; und ein umbenannter Geschäftspartner-Code ist ein neuer Kunden-Schlüssel.