typische Anwendungsfälle

einfache Admin-Aufgaben

Selten auftretende Admin-Aufgaben lassen sich gut mittels Python-Scripten automatisieren. Es ist sehr einfach möglich, auf die DB, aber auch auf SOAP-Schnittstelle der APP-Serverse zuzugreifen. Zudem ist rudimentärer Zugriff auf ASMX-Seiten implementiert. Ich habe dies vor allem für Wartungsarbeiten an Anpassungstabellen genutzt, die für eigene Erweiterungen entwickelt wurden.

Als triviales Beispiel sucht folgender Code alle DOCUMENTS Einträge in Artikeln (angezeigt als Bild in ArtikelRec.aspx), für die Datei, auf die verwiesen wird, nicht im Dateisystem existiert. Diese fehlenden Dateien werden ausgegeben und das Feld DOCUMENTS gelöscht. Das Löschen erfolgt dabei über useXML, so dass die Felder UPDDATE und UPDUSER korrekt gesetzt werden.

 1import pathlib
 2import PyAPplus64
 3import applus_configs
 4from typing import Optional
 5
 6
 7def main(confFile: pathlib.Path, updateDB: bool, docDir: Optional[str] = None) -> None:
 8    server = PyAPplus64.applus.applusFromConfigFile(confFile)
 9
10    if docDir is None:
11        docDir = str(server.scripttool.getInstallPathWebServer().joinpath("DocLib"))
12
13    sql = PyAPplus64.sql_utils.SqlStatementSelect("ARTIKEL")
14    sql.addFields("ID", "ARTIKEL", "DOCUMENTS")
15    sql.where.addConditionFieldStringNotEmpty("DOCUMENTS")
16
17    for row in server.dbQueryAll(sql):
18        doc = pathlib.Path(docDir + row.DOCUMENTS)
19        if not doc.exists():
20            print("Bild '{}' für Artikel '{}' nicht gefunden".format(doc, row.ARTIKEL))
21
22            if updateDB:
23                upd = server.mkUseXMLRowUpdate("ARTIKEL", row.ID)
24                upd.addField("DOCUMENTS", None)
25                upd.update()
26
27
28if __name__ == "__main__":
29    main(applus_configs.serverConfYamlTest, False)

Man kann alle Python Bibliotheken nutzen. Als Erweiterung wäre es in obigem Script zum Beispiel einfach möglich, alle BMP-Bilder zu suchen, nach PNG zu konvertieren und den DB-Eintrag anzupassen.

Ad-hoc Reports

APplus erlaubt es mittels Jasper-Reports, flexible und schöne Reports zu erzeugen. Dies funktioniert gut und ist für regelmäßig benutzte Reports sehr sinnvoll.

Für ad-hoc Reports, die nur sehr selten oder sogar nur einmal benutzt werden, ist die Erstellung eines Jasper-Reports und die Einbindung in APplus jedoch zu zeitaufwändig. Teilweise genügen die Ergebnisse einer SQL-Abfrage, die direkt im MS SQL Server abgesetzt werden kann. Wird es etwas komplizierter oder sollen die Ergebnisse noch etwas verarbeitet werden, bietet sich evtl. Python an.

Folgendes Script erzeugt zum Beispiel eine Excel-Tabelle, mit einer Übersicht, welche Materialen wie oft für Artikel benutzt werden:

 1import PyAPplus64
 2import applus_configs
 3import pathlib
 4
 5
 6def main(confFile: pathlib.Path, outfile: str) -> None:
 7    server = PyAPplus64.applus.applusFromConfigFile(confFile)
 8
 9    # Einfache SQL-Anfrage
10    sql1 = ("select Material, count(*) as Anzahl from ARTIKEL "
11            "group by MATERIAL having MATERIAL is not null "
12            "order by Anzahl desc")
13    df1 = PyAPplus64.pandas.pandasReadSql(server, sql1)
14
15    # Sql Select-Statements können auch über SqlStatementSelect zusammengebaut
16    # werden. Die ist bei vielen, komplizierten Bedingungen teilweise hilfreich.
17    sql2 = PyAPplus64.SqlStatementSelect("ARTIKEL")
18    sql2.addFields("Material", "count(*) as Anzahl")
19    sql2.addGroupBy("MATERIAL")
20    sql2.having.addConditionFieldIsNotNull("MATERIAL")
21    sql2.order = "Anzahl desc"
22    df2 = PyAPplus64.pandas.pandasReadSql(server, sql2)
23
24    # Ausgabe als Excel mit 2 Blättern
25    PyAPplus64.pandas.exportToExcel(outfile, [(df1, "Materialien"), (df2, "Materialien 2")], addTable=True)
26
27
28if __name__ == "__main__":
29    main(applus_configs.serverConfYamlTest, "myout.xlsx")

Dieses kurze Script nutzt Standard-Pandas Methoden zur Erzeugung der Excel-Datei. Allerdings sind diese Methoden in den Aufrufen von pandasReadSql und exportToExcel gekapselt, so dass der Aufruf sehr einfach ist. Zudem ist es sehr einfach, die Verbindung zur Datenbank und zum APP-Server mittels der YAML-Konfigdatei herzustellen. Bei diesem Aufruf kann optional ein Nutzer und eine Umgebung übergeben werden, die die Standard-Werte aus der YAML-Datei überschreiben. pandasReadSql nutzt intern completeSQL, so dass der für die Umgebung korrekte Mandant automatisch verwendet wird.

Anbindung eigener Tools

Ursprünglich wurde PyAPplus64 für die Anbindung einer APplus-Anpassung geschrieben. Diese Anpassung ist als Windows-Service auf einem eigenen Rechner installiert und überwacht dort ein bestimmtes Verzeichnis. Bei Änderungen an Dateien in diesem Verzeichnis (Hinzufügen, Ändern, Löschen) werden die Dateien verarbeitet und die Ergebnisse an APplus gemeldet. Dafür werden DB-Operationen aber auch SOAP-Calls benutzt. Ebenso wird auf die SysConf zugegriffen.

Viele solcher Anpassungen lassen sich gut und sinnvoll im App-Server einrichten und als Job regelmäßig aufrufen. Im konkreten Fall wird jedoch für die Verarbeitung der Dateien viel Rechenzeit benötigt. Dies würde dadurch verschlimmert, dass die Dateien nicht auf der gleichen Maschine wie der App-Server liegen und somit viele, relativ langsame Dateizugriffe über das Netzwerk nötig wären. Hinzu kommt, dass die Verarbeitung der Dateien dank existierender Bibliotheken in Python einfacher ist.

PyAPplus64 kann für solche Anpassungen eine interessante Alternative zur Implementierung im App-Server oder zur Entwicklung eines Tools ohne spezielle Bibliotheken sein. Nach Initialisierung des Servers:

import PyAPplus64

server = PyAPplus64.applus.applusFromConfigFile("my-applus-server.yaml")

bietet P2APplus64 wie oben demonstriert einfachen lesenden und schreibenden Zugriff auf die DB. Hierbei werden automatisch die für die Umgebung nötigen Mandanten zu den SQL Statements hinzugefügt. Zudem ist einfach ein Zugriff auf die Sysconf möglich:

print (server.sysconf.getString("STAMM", "MYLAND"))
print (server.sysconf.getList("STAMM", "EULAENDER"))

Dank der Bibliothek zeep ist es auch sehr einfach möglich, auf beliebige SOAP-Methoden zuzugreifen. Beispielsweise kann auf die Sys-Config auch händisch, d.h. durch direkten Aufruf einer SOAP-Methode des APP-Servers zugegriffen werden:

client = server.getAppClient("p2system", "SysConf");
print (client.service.getString("STAMM", "MYLAND"))