Kategorien
SAP

SAP BAS: Adressabgleich

In unserem Projekt „Business Address Service“ im SAP System bauen wir derzeit eine Adressprüfung gegen das öffentliche Firmenregister ein.

Unglaublich guter Service, den die GfUD nutzt: Plausibilitätsprüfung und Ergänzung zu ihrem Kundenverzeichnis.

Plausibilitätsprüfungen und wertvolle Ergänzungen für ihr CRM und SD. Ein Vorteil für ihre Risikoabschätzung und Herstellung der Transparenz von gemeinsamen Geschäften.

Das Projekt (2019) wird nicht veröffentlicht – wer noch teilnehmen, oder den Dienst ausserhalb von SAP System nutzen möchte, mag mich kontaktieren:

Telefon 02202 989 12 17

Kategorien
SAP Schulung

SAP und Agorum als DMS Lösung

Es sind Umstände vorstellbar, in denen die Integration von Belegen in das SAP System garnicht gewünscht sind. Große Steuerberater erhalten die Belege als Scan von ihren Mandanten und ein kopieren in das SAP eigene DMS, dem SAP Content Server, ist garnicht gewünscht. Es ist aber Standard, die Originalbelege zum Systembeleg abzulegen, zumindest eine Referenz herzustellen. Das Belegfeld „Referenznummer“ dient zur Aufnahme der Fremdbelegnummer und hat im weiteren Belegprozess eine Bedeutung. Das vermerken der Systembelegnummer auf dem Originalbeleg ist angeraten und wird in der Praxis meisst per Hand vollzogen.

Wenn ich mit meinem Lieblings-DMS, dem von Agorum, arbeite, arbeite ich auf zwei Bildschirmen. Links ist die Buchungsmaske, rechts das Dokument. Wenn ich links buche, wird eine Systembelegnummer generiert die ich rechts auf dem Originalbeleg vermerken sollte. So ist ein suchen und finden von Belegen von beiden Applikationen aus möglich.

Das gilt es zu automatisieren. Ich will dabei garnicht zu sehr ins Detail gehen, etwas Vorkenntnis setze ich voraus – im Zweifel fragen!

Möglichkeiten, in die SAP Software manipulativ einzuwirken, gibt es viele. Eine sehr schöne und einfache Möglichkeit sind BTE’s ( Business Transaction Events ).  Der Name lässt schon auf die Systematik schliessen: In den Arbeitsprozessen werden zu bestimmten Zeitpunkten, einfach gesagt, nach geschaut, ob der Kunde an diesem Punkt eigenen Programmcode ablaufen lassen möchte. Wirklich sehr einfach dargestellt!

Solche Eventtimes existieren in jedem Arbeitsprozess und zu mehreren sinnvollen Zeitpunkten. Den richtigen Zeitpunkt zu finden, kann in stundenlangen Suchorgien ausarten. Wenn man aber das Wochende mit dem austesten glücklich verbracht hat, hat man etwas gelernt. Kurz: Für unsere Zwecke hat sich der Zeitpunkt 1030 ganz anständig vorgestellt. Wir sprechen von einem Zeitpunkt im Arbeitsprozess „Beleg buchen“ welcher nach der Belegprüfung und nach dem „speichern“ aber vor dem COMMIT WORK liegt. Zu diesem Zeitpunkt steht fest, das und mit welcher Belegnummer gespeichert wird. Im Dictionary befinden sich für jeden Zeitpunkt ein beispielhafter Funktionsbaustein der in seinen Parametern nicht verändert werden darf. Dieser wird in den eigenen Namensraum kopiert. ( Listing )

Bevor es an die Programmierung geht, kurz ein Gedanke zum pro cedere. Der Buchhalter bucht, zum Beispiel, über die FB50 Belege ein. Dort stehen uns Felder für den Belegkopf zur Verfügung. Wenn wir nun eine Verbindung zu einem externen Originalbeleg herstellen wollen, bedient man sich allgemein dem Referenzfeld. Wie schon weiter oben gesagt, hat das Feld eine Aufgabe. Nämlich die, der Zuordnung beim maschinellen Ausgleich. Im Agorum DMS liegt ein File, mit einem Namen und einer Objekt ID. Hier können wir also keine einfache Verbindung zwischen Systembeleg und Originalbeleg assoziieren. Ich habe es ersteinmal so gelöst, ohne Programmierung von kundeneigenen Feldern, das Feld „Belegkopftext“ Zweck zu entfremden.

Dazu habe ich eine neue Belegart „AG“ erstellt und das Feld  „Belegkopftext“  zum Mussfeld gemacht. Damit ist zwingend das Feld mit der Objekt ID des im Agorum DMS befindlichen Originalbelegs zu befüllen.

Wenn nun die Buchung verbucht wird, kommt es zum Event 1030 zu dem die Belegkopfdaten als Notiz an den Originalbeleg im Agorum DMS hinzu gefügt werden sollen. Dazu stellt Agorum eine REST API zur Verfügung. Über URL mit POST/GET angesprochen, wird eine Antwort per XML zurück gegeben. Im SAP System bediene ich mich dazu der Klasse CL_HTTP_CLIENT. ( Listing )

Wir sehen in den Zeilen 45 bis 65 das zunächst der http Client initialisiert  und eine Session ID angefordert wird. Die lokale Variable lv_bin enthält nun die XML Antwort von Agorum als XSTRING und wird in den Zeilen 95 bis 100 in eine itab gelesen. Beim programmieren kommt man nicht ohne Debugger weiter, denn der Aufbau des XML ist nicht klar. Das Ergebnis wird schlicht als „value“ übertragen und hängt demnach von der Anforderung ab. Werden mehrer Anforderungen gestellt, heißen alle Werte „value“.

Die Zeilen 80 bis 93, das Suchen nach dem Filenamen, hat zwei Gründe: Es kann eine Tabelle aufgebaut werden, in der die Verbindung Objekt ID, Filename und Systembelegnummer protokolliert wird. Und es war nicht möglich, nach dem Abfragen der Session ID direkt die Notiz zu generieren. Es kommt ohne vorheriges GET vor dem POST zur Fehlermeldung seitens Agorum DMS.

In den Zeilen 112 bis 135 wird es haarig. Uns stehen an dieser Stelle alle Daten zur Verfügung: Objekt ID, Session ID und Belegdaten. Diese müssen als escaped JSON formatiert werden. Nach dem senden ist die Zeile 142 entscheident. Erfolgt nach dem send kein receive, wird die Notiz nicht erstellt.

Dieser neue kundeneigene Funktionsbaustein ist nun, nach dem aktivieren, dem Event zu zuordnen. Über die Transaktionen BF24 und BF34 können wir unser Produkt ersteinmal benennen, aktivieren und einem Zeitpunkt, hier 00001030, zuordnen.

Das Ergebnis ist, das wir im SAP System an der Belegart und dem Belegtext erkennen, das es einen Originalbeleg im Agorum DMS gibt. Im Agorum DMS können wir schnell an der vorhandenen Notiz erkennen, das eine Buchung im SAP System vorgenommen wurde. Im Detail können wir nach Systembelegnummern, Buchungsdatum usw. suchen.

Eine einfache und praktikable Lösung.

Kategorien
SAP Schulung

SAP Zinsrechnung – Verwendbarkeit

Kann man das Beispiel aus meinem Beitrag (Link) so übernehmen? Nein!

Natürlich darf der Code hier kopiert werden. Alle Code sind aber nur Beispiele und Arbeitsvorlagen. Nicht zuletzt existiert die Seite, weil sie auch mir als Merkhilfe für bestimmte Dinge dient.

Bei einer Zinsrechnung ist darauf zu achten, für wen ich was rechne! In unserem Beispiel wird der Zins vom Zins mit berechnet. Das ist nach §289 BGB nicht zulässig. Auch ist die Frage ob eine lineare Berechnung gefragt ist. Also, ist der Code in jedem Fall an die Bedürfnisse anzupassen und niemals blind zu kopieren und produktiv zu nutzen!

Zinsrechnung unter Beachtung 286BGB ( kein Zins vom Zins )

In dem Listing (Link) ist die Zeile 112 fraglich. Nimmt man sie heraus und bildet über das ALV eine Aggregation, ist diese Rechnung rechtlich korrekt für Kredite nach Effektivzinsmethode mit Zinsaufschlag auf den Leitzins unter Berücksichtigung, das der Zins nicht vom Zins gerechnet wird.

Aufbau des ALV mit Summenaggregation

Kategorien
SAP Schulung

SAP Zinsrechnung

Die Zinsrechnung ist weitaus mehr als Zins = Betrag * Zinssatz / 100. Es tauchen Fragen auf wie: Ist der Zins in einer Periode linear oder exponentiell verteilt. Ist der Zinssatz auf 365 oder, banküblich, auf 360 Tage zu verteilen. Und, und, und. Aus dem Schaubild der SAP geht das Prinzip hervor, wie und womit die Zinsrechnung im System realisiert wird.

SAP Zinsrechnung
Copyright by SAP

Tabelle Leitzins T056B
Tabelle Leitzins T056B

In der Realität wird zur Bestimmung eines Zinssatzes u.a. die Tabelle T056P befragt, in der auch der EZB Leitzins abgespeichert ist. In dem Schulungssystem des letzten Workshops war die Tabelle leer, weshalb ich sie mit den Echtdaten der EZB gefüllt habe.

An der Stelle ist schon der Typ des Datenelementes zu beachten: Der Zins ist vom Datentyp DEC, 10 Zeichen lang davon 7 Nachkommastellen und entspricht dem ABAP Datentyp p (packed). Das ist wichtig in Bezug auf die Nutzung der im ersten Bild angesprochenen Funktionsbausteinen, die als Importparameter für den Zinssatz den ABAP Datentyp f (float) voraus setzen! An der Stelle habe ich meinen Teilnehmern das Nachschlagen unter dem  Stichwort „Festpunktarithmetik“ anheim gestellt, denn das habe ich zur Erhöhung des Spaßfaktors deaktiviert! Die Folgen können hier nachgelesen werden. (Link).

Zunächst aber die Problematik in der Betrachtung des Zeitraums: Eine Bank rechnet nicht nach Kalendar. Ein Jahr hat für die Bank 360 Tage, ein Monat immer 30 Tage. Es hat den Vorteil, das man über Schaltjahre garnicht erst nachdenken muss. Ein Zeitraum, also die Anzahl Tage zwischen zwei Daten, ist einfach zu programmieren. Der Datentyp DATS, ABAP Datentyp d, ist ein CLIKE also ein Feld vom Typ  Like Charakter. Das Format ist „YYYYMMTT“. Es lässt sich mit den Werkzeugen der Stringmanipulation, dem Textoffset, bequem auslesen und auch Rechenoperationen sind systemseitig realisiert. So funktioniert „TAGE = DATUM2 – DATUM1“ genau so wie „Monate = DATUM2+4(2) – DATUM1+4(2)“. Genau das wird mit dem Funktionsbaustein FIMA_DAYS_BETWEEN_TWO_DATES realisiert, dem wir uns problemlos bedienen können. Die Berechnung nach Bankstandard ist auch hier Standard!

In dem Listing (Link) ist in Zeile 29 zu sehen, das der Datumswert, wie auch in der Tabelle T056P, als invertiertes

28.07.2018 und 01.01.2020 Normal und invertiert
28.07.2018 und 01.01.2020 Normal und invertiert

Datum erfasst wird. Nach der Konvertierung suchen wir aus der Tabelle den zum Startzeitpunkt gültigen Zinssatz und addieren den in Zeile 30 abgefragten Zinswert welcher über dem Leitzins errechnet werden soll.

Stehen die Parameter Basisbetrag, Startdatum und Zinssatz soweit fest, kann der Zins mit dem Funktionsbaustein FIMA_INTEREST_COMPUTE errechnet werden. Schauen wir in die Zeile 102 auf den Importparameter i_pzins. Der Datentyp ist f (float). Mit ausgeschalteter Festpunktarithmetik wird jetzt,  schon beim Casting der Werte, der Wert mit dem Typ DEC als Ganzzahl interpretiert. Wir sagten: DEC 10 Stellen, 7 Dezimal. Wenn der Wert vorher 10,1000000 war, ist er jetzt 101000000. Genau DAS passiert in Zeile 96. In Zeile 97 ist eine mögliche Korrektur, nämlich die Division mit 10000000 – das Komma um sieben Stellen verschoben. Statt solcher unschönen Klimmzügen, geben wir die Werte einem Funktionsbaustein in dessen Funktionsgruppendefinition die Festpunktarithmetik aktiviert ist. Dieser Funktionsbaustein Y_ZAHL übergibt schlicht den Wert mit dem Typ p (packed) and den Typ f (float) unter Beachtung des Dezimaltrenners.

Die Daten so, korrekt, dem Funktionsbaustein FIMA_INTEREST_COMPUTE übergeben, wird unter Beachtung der Zinsrechnungsmethode ( Standard ist die lineare Verteilung auf 360 Tage ) und des Verteilungsquotient ( Tage / Basistage ) der Zins errechnet.

entscheidende Formel im FB FIMA_INTEREST_COMPUTE
entscheidende Formel im FB FIMA_INTEREST_COMPUTE

In Zeile 115 bauen wir so unsere Tabelle auf, die durch den Loop in den Zeilen 45 bis 121, maximal soviele Zeilen aufweist wie auch Zinssätze in der Tabelle T056P vorhanden sind. Im Echtsystem ist das Vorgehen so nicht empfehlenswert, da die Tabelle im Normalfall mehr als 88.000 Einträge hat.

Kategorien
Schulung

TicTacToe – Wargames

Möchte man in unserem Beispiel mit der Anzahl Spieler 0, wie im Klassiker War Games, das beide Spieler strategisch vorgehen, ist im Unterprogramm „spielen“ folgendes zu ändern.

Es wird zuerst, ist der Spieler SAP am Zug, der Defensivzug durch die Summe der Zeilen,Spalten oder Diagonalen mit dem Wert 10 bestimmt. Danach der Offensivzug mit der Summe 2. Ist der Spieler USR am Zug genau umgekehrt. Ist Defensiv gegen 2 vorzugehen und anschließend ob die Summe 10 zum Gewinn führt.

Jetzt kommt es meisst zum Unentschieden.

Kategorien
Schulung

TicTacToe – Strategie

Im Artikel (Link) erwähnte ich eine Offensiv- und Defensivstrategie für den alten Übungscode den ich zur Anschauung (Link) überarbeitet habe.

Strategiedaten eingeblendet damit sie ohne Debugger im Spielverlauf beobachtet werden können.
Strategiedaten eingeblendet damit sie ohne Debugger im Spielverlauf beobachtet werden können.

Im Code sehen wir, das zunächst Spielzüge wie im Original per Zufallszahl ermittelt werden. Das gilt für den Spieler SAP (wer=1) immer und für den Spieler USR (wer=5) wenn die Anzahl der Spieler Null ist (a=0). Vor dem setzen des Zuges, wird der Zug für den Spieler SAP strategisch gesprüft. Zunächst Defensiv – das heisst, hat der Spieler USR zwei Züge gemacht (ein Zug hat den Wert 5) ist die Summe der Zeilen, Spalten oder Diagonalen gleich 10. Ist sie gleich 10, bedeutet es, das der nächste Zug des Spielers USR  zum Gewinn führt. Es wird also das freie Feld in der Zeile, Spalte oder Diagonalen gesucht und die Werte x und y, für den nächsten Zug des Spielers SAP, angepasst.

Danach erfolgt die Offensivprüfung. (Im Code sehen wir die Aufrufe  PERFORM strategie USING 10. und PERFORM strategie USING 2.) Hier wird nun geprüft ob der nächste Zug des Spielers SAP zum Gewinn führt. Es ist sinnvoller direkt zu gewinnen, als sich zu verteidigen. Die Werte x und y können also wieder manipuliert werden. KÖNNEN! Wie gesagt, die Werte x und y sind Zufallszahlen und bleiben unverändert wenn keine Strategie greift. Das passiert solange keine zusammenhängende Züge gemacht werden, wie zum Beispiel zum Beginn des Spiels.

Genau hier liegt jetzt die Chance des Spielers USR. Nur noch mit Glück und ausgefeilter Taktik kann USR noch gewinnen. Zum Beispiel führen die Züge 2,1    3,3    2,2   mit dem finalen Schlag auf 2,3 zum Gewinn. WENN keine Zufallszahl in die Quere kommt. Das Geheimnis liegt darin, zwei mögliche Gewinnsituationen zu stellen. Mit 2,1    3,3    „bemerkt“ die Strategie noch nichts. Kommt jetzt 2,2 hinzu, habe ich in der zweiten Zeile und in der Diagonalen die Summe 10. Für den User SAP wird jetzt vorrangig ein Zug in der Diagonalen vorgeschlagen, also auf 1,1. Jetzt kann USR in der zweiten Zeile gewinnen.

Kategorien
Schulung

TicTacToe – Reloaded

Lang ist es her, aber gerne benutze ich den alten Code und lasse ihn auch noch auf einer PDP11 laufen. Im letzten Workshop sprachen wir über die Möglichkeiten der Programmierung eines Reports in ABAP. Wir wissen, das ein Report für die dynamische, interaktive Darstellung von Listen gedacht ist. Als Übung, damit die laufzeitabhängigen Ereignisse eines Reports klar werden, habe ich den original DEC Code des Spiels „Tic Tac Toe“ gegeben der analysiert und in ABAP realisiert werden sollte.

Hier nun eine kurze Vorstellung meiner Musterlösung.

Der Sinn des Spiels ist klar – drei Felder, in einer Reihe, Spalte oder Diagonalen sind zu besetzen. Wir erkennen im Original, in den Zeilen 1090 und folgenden, das die Züge der Maschine per Zufallszahl erzeugt werden.

Das ist auch so in ABAP realisierbar. Es stehen ein Funktionsbaustein aus der Gruppe QF05 (QF05_RANDOM_INTEGER) sowie die Klasse CL_ABAP_RANDOM_INT zur Verfügung.

Expliziet wird der Zug geprüft, nämlich ob das Feld bereits belegt wurde und ob der Zug zum Gewinn der Partie führt. Das Vorgehen, auch gerade mit den im Original verwendeten Befehlen GOTO und GOSUB, ist im Report nicht möglich da er nicht prozedual abläuft. Um nah, wie die Aufgabe lautet, am Original zu bleiben, empfiehlt sich für den Ersatz des GOSUB der Befehl PERFORM.

Um die Sache etwas interessanter zu machen, habe ich zwei Dinge berücksichtig. In der Grundliste des Reports (SY-LSIND = 0) kann „Anzahl Spieler 0“ eingegeben werden. Das Programm spielt dann beide Spieler – wir erinnern uns an den Klassiker „War Games“. Eine Defensivstrategie ermöglicht dem Spieler „SAP“ einen Gewinnzug des Gegners zu verhindern. Taktisch wird nach jedem Zug die Summe der Zeilen, Spalten und Diagonalen errechnet und dem entsprechend ein Zug vereinbart. Dennoch ist es dem User möglich zu gewinnen, nämlich dann, wenn es mehr als eine Gewinnmöglichkeit gibt. Eine Offensivstrategie ist nicht implementiert – das kann als

Zusatzaufgabe verstanden werden. Offensiv heisst, das Programm stellt nicht fest ob oder das der nächste Zug zum Gewinn führt. Gibt es nichts zu verteidigen, wird eine Zufallszahl über den nächsten Zug entscheiden!

Kategorien
SAP Schulung

ABAP Code 740 zu 702

In den neueren Spielereien unseren hochgeschätztem Enno Wulff wird der überarbeitete ABAP Befehlssatz verwendet. Ich verwende noch den Stand 702 und kann so einfach seinen Code nicht übernehmen.

So verwendet er gerne die neue Kurzschreibweise mit der eine Klasse instanziiert wird: NEW x(  ).

Seht in seinen Code unter den Zeilen 20 und 98 und erinnern wir uns an BC401 Seite 59.

Die Zeile 20 mit „timer = NEW #( )“ ändern wir durch –> „CREATE OBJECT timer.“ und das „NEW main( )>start( ).“ ersetzen wir mit

„DATA m TYPE REF TO main.
CREATE OBJECT m.
m->start( ).“

Dann läuft die Sache auch und ist eine tolle Vorlage für so manch Lösung.

 

Kategorien
SAP Schulung

Kalkulierende Felder

Sehr praktisch im täglichen Umgang sind kalkulierende, also selbst rechnende Felder. Will man zB. im Buchungsvorgang Skonto für Teilbeträge buchen, kann die Rechenoperation einfach in das Soll/Haben Feld eingetragen werden. Das ist im Microsoft Dynamics NAV in jedem numerischen Feld vorgesehen – es wird nach der „Punkt vor Strich“ Regel gerechnet. In der Praxis ist das nicht immer gewollt.

Der Chef legt zum Beispiel eine Tankquittung vor auf der auch neben dem abzugsfähigen Treibstoff und einer Dose Öl auch Zigarretten und ein Lolli für das Kind aufgeführt ist. Praktischer Weise rechnen wir 10 Euro plus 5 Euro mal 19% und nicht (10+5)*19/100. Im NAVISION bleibt keine Wahl, das Verfahren ist nicht änderbar. Es funktioniert nur Punkt-vor-Strich.

In unserem SAP System sind die Möglichkeiten offen. Als Demo habe ich einmal alle Möglichkeiten aufgeführte.

Der Standard Funktionsbaustein ‚EVAL_FORMULA‘ ist in der Lage ein String mit „10+5*0,19“ zu verarbeiten und nach der PvS Regel zu berechnen. Es ist also keine Schwierigkeit in einem PAI das Eingabefeld durch diesen Funktionsbaustein verarbeiten zu lassen und das selbt rechnende Feld ist realisiert.

Ich persönlich halte das für unpraktisch. Ähnlich wie der SAP Calculator, den wir mit dem Funktionsbaustein ‚FITRV_CALCULATOR‘ aufrufen können, läßt sich auch der Eingabestring zerlegen und sequenziell verarbeiten.

Wie in dem Listing zu sehen ist, zerlege ich den Eingabestring in eine Interne Tabelle. Die Zeichen + – * / separieren die Zahlen und rechnen entsprechend der Operation sequenziell.

Letztendlich mag es eine Sache der Gewöhnung sein. Mich interessieren die Erfahrungen die andere gemacht haben.

Kategorien
SAP

SAP: DynPro Layout Editor

In der Entwicklung (SE80) eines Web DynPro’s ist der Umstand, das der Editor auf Web Komponenten zur Anzeige des Layouts zurück greift, lästig.  In einer Standard Konfiguration wird beim Zugriff eine weitere Authentifizierung verlangt.

Sehr viele Anleitungen lassen sich im Netz finden die das Problem zum Beispiel durch das SSO umgehen. Für eine schnelle Lösung, die nur die Entwicklungsumgebung ohne Anmeldung laufen lässt, gehe ich wie folg vor:

  1. SICF Service Anmeldung
    SICF Service Anmeldung

    SU01 —> einen Service-User anlegen.

  2. SICF  —> wählen Sie unter dem Default Host den Eintrag sap/bc/wdvd und öffnen durch doppelklick die Eigenschaften.
    Dort, im Reiter „Anmelde-Daten“, die User Daten des zuvor angelegten Service User eintragen.

Das hat zur Folge, das NUR beim Auftruf des ViewDesigners in der SE80, eine automatische Athentifizierung mit dem Service User geschieht.

Andere Lösungsvorschläge sind willkommen!