Beispiele¶
Im Verzeichnis examples
finden sich Python Dateien, die die Verwendung von PyAPplus64 demonstrieren.
Config-Dateien¶
Viele Scripte teilen sich Einstellungen. Beispielsweise greifen fast alle Scripte irgendwie auf APplus zu und benötigen Informationen,
mit welchem APP-Server, welchem Web-Server und welcher Datenbank sie sich verbinden sollen. Solche Informationen, insbesondere die Passwörter, werden nicht in
jedem Script gespeichert, sondern nur in den Config-Dateien. Es bietet sich wohl meist an, 3 Konfigdateien zu erstellen, je eine für
das Deploy-, das Test- und das Prod-System. Ein Beispiel ist im Unterverzeichnis examples/applus-server.yaml
zu finden.
1# Einstellung für die Verbindung mit dem APP-, Web- und DB-Server.
2# Viele der Einstellungen sind im APplus Manager zu finden
3
4appserver : {
5 server : "some-server",
6 port : 2037,
7 user : "asol.projects",
8 env : "default-umgebung" # hier wirklich Umgebung, nicht Mandant verwenden
9}
10webserver : {
11 baseurl : "http://some-server/APplusProd6/",
12 user : null, # oft "ASOL.Projects", wenn nicht gesetzt, wird aktueller Windows-Nutzer verwendet
13 userDomain : null, # Domain für ASOL.PROJECTS
14 password : null # das Passwort
15}
16dbserver : {
17 server : "some-server",
18 db : "APplusProd6",
19 user : "SA",
20 password : "your-db-password"
21}
Damit nicht in jedem Script immer wieder neu die Konfig-Dateien ausgewählt werden müssen, werden die Konfigs für
das Prod-, Test- und Deploy-System in examples/applus_configs.py
hinterlegt. Diese Datei wird in allen Scripten importiert,
so dass das Config-Verzeichnis und die darin enthaltenen Configs einfach zur Verfügung stehen. Zudem werden in dieser Datei auch alle verwendeten
Kombinationen aus System und Umgebung hinterlegt. So kann in Scripten auch eine Auswahl des Systems implementiert werden.
1import pathlib
2from PyAPplus64.applus import APplusServerConfigDescription
3
4basedir = basedir = pathlib.Path(__file__) # Adapt to your needs
5configdir = basedir.joinpath("config")
6
7serverConfYamlDeploy = configdir.joinpath("applus-server-deploy.yaml")
8serverConfYamlTest = configdir.joinpath("applus-server-test.yaml")
9serverConfYamlProd = configdir.joinpath("applus-server-prod.yaml")
10
11
12serverConfDescProdEnv1 = APplusServerConfigDescription("Prod/Env1", serverConfYamlProd, env="Env1")
13serverConfDescProdEnv2 = APplusServerConfigDescription("Prod/Env2", serverConfYamlProd, env="Env2")
14serverConfDescTestEnv1 = APplusServerConfigDescription("Test/Env1", serverConfYamlTest, env="Env1")
15serverConfDescTestEnv2 = APplusServerConfigDescription("Test/Env2", serverConfYamlTest, env="Env2")
16serverConfDescDeploy = APplusServerConfigDescription("Deploy", serverConfYamlDeploy)
17
18serverConfDescs = [
19 serverConfDescProdEnv1,
20 serverConfDescProdEnv2,
21 serverConfDescTestEnv1,
22 serverConfDescTestEnv2,
23 serverConfDescDeploy
24]
read_settings.py
¶
Einfaches Beispiel für Auslesen der SysConf und bestimmter Einstellungen.
1# Einfaches Script, das verschiedene Werte des Servers ausliest.
2# Dies sind SysConfig-Einstellungen, aber auch der aktuelle Mandant,
3# Systemnamen, ...
4
5import pathlib
6import PyAPplus64
7import applus_configs
8from typing import Optional, Union
9
10
11def main(confFile: Union[str, pathlib.Path], user: Optional[str] = None, env: Optional[str] = None) -> None:
12 server = PyAPplus64.applusFromConfigFile(confFile, user=user, env=env)
13
14 print("\n\nSysConf Lookups:")
15
16 print(" Default Auftragsart:", server.sysconf.getString("STAMM", "DEFAULTAUFTRAGSART"))
17 print(" Auftragsarten:")
18 arten = server.sysconf.getList("STAMM", "AUFTRAGSART", sep='\n')
19 if not arten:
20 arten = []
21 for a in arten:
22 print(" - " + a)
23
24 print(" Firmen-Nr. automatisch vergeben:", server.sysconf.getBoolean("STAMM", "FIRMAAUTOMATIK"))
25 print(" Anzahl Artikelstellen:", server.sysconf.getInt("STAMM", "ARTKLASSIFNRLAENGE"))
26
27 print("\n\nScriptTool:")
28
29 print(" CurrentDate:", server.scripttool.getCurrentDate())
30 print(" CurrentTime:", server.scripttool.getCurrentTime())
31 print(" CurrentDateTime:", server.scripttool.getCurrentDateTime())
32 print(" LoginName:", server.scripttool.getLoginName())
33 print(" UserName:", server.scripttool.getUserName())
34 print(" UserFullName:", server.scripttool.getUserFullName())
35 print(" SystemName:", server.scripttool.getSystemName())
36 print(" Mandant:", server.scripttool.getMandant())
37 print(" MandantName:", server.scripttool.getMandantName())
38 print(" InstallPath:", server.scripttool.getInstallPath())
39 print(" InstallPathAppServer:", server.scripttool.getInstallPathAppServer())
40 print(" InstallPathWebServer:", server.scripttool.getInstallPathWebServer())
41 print(" ServerInfo - Version:", server.scripttool.getServerInfo().find("version").text)
42
43 client = server.getWebClient("dbenv/dbenv.asmx")
44 print("WEB Environment:", client.service.getEnvironment())
45
46if __name__ == "__main__":
47 main(applus_configs.serverConfYamlTest)
check_dokumente.py
¶
Einfaches Beispiel für lesenden und schreibenden Zugriff auf APplus Datenbank.
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)
adhoc_report.py
¶
Sehr einfaches Beispiel zur Erstellung einer Excel-Tabelle aus einer SQL-Abfrage.
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")
mengenabweichung.py
¶
Etwas komplizierteres Beispiel zur Erstellung einer Excel-Datei aus SQL-Abfragen.
1# Erzeugt Excel-Tabellen mit Werkstattaufträgen und Werkstattauftragspositionen mit Mengenabweichungen
2
3import datetime
4import PyAPplus64
5import applus_configs
6import pandas as pd # type: ignore
7import pathlib
8from typing import Tuple, Union, Optional
9
10
11def ladeAlleWerkstattauftragMengenabweichungen(
12 server: PyAPplus64.APplusServer,
13 cond: Union[PyAPplus64.SqlCondition, str, None] = None) -> pd.DataFrame:
14 sql = PyAPplus64.sql_utils.SqlStatementSelect("WAUFTRAG w")
15 sql.addLeftJoin("personal p", "w.UPDUSER = p.PERSONAL")
16
17 sql.addFieldsTable("w", "ID", "BAUFTRAG", "POSITION")
18 sql.addFields("(w.MENGE-w.MENGE_IST) as MENGENABWEICHUNG")
19 sql.addFieldsTable("w", "MENGE", "MENGE_IST",
20 "APLAN as ARTIKEL", "NAME as ARTIKELNAME")
21 sql.addFields("w.UPDDATE", "p.NAME as UPDNAME")
22
23 sql.where.addConditionFieldGe("w.STATUS", 5)
24 sql.where.addCondition("abs(w.MENGE-w.MENGE_IST) > 0.001")
25 sql.where.addCondition(cond)
26 sql.order = "w.UPDDATE"
27 dfOrg = PyAPplus64.pandas.pandasReadSql(server, sql)
28
29 # Add Links
30 df = dfOrg.copy()
31 df = df.drop(columns=["ID"])
32 # df = df[['POSITION', 'BAUFTRAG', 'MENGE']] # reorder / filter columns
33
34 df['POSITION'] = PyAPplus64.pandas.mkHyperlinkDataframeColumn(
35 dfOrg,
36 lambda r: r.POSITION,
37 lambda r: server.makeWebLinkWauftrag(
38 bauftrag=r.BAUFTRAG, accessid=r.ID))
39 df['BAUFTRAG'] = PyAPplus64.pandas.mkHyperlinkDataframeColumn(
40 dfOrg,
41 lambda r: r.BAUFTRAG,
42 lambda r: server.makeWebLinkBauftrag(bauftrag=r.BAUFTRAG))
43
44 colNames = {
45 "BAUFTRAG": "Betriebsauftrag",
46 "POSITION": "Pos",
47 "MENGENABWEICHUNG": "Mengenabweichung",
48 "MENGE": "Menge",
49 "MENGE_IST": "Menge-Ist",
50 "ARTIKEL": "Artikel",
51 "ARTIKELNAME": "Artikel-Name",
52 "UPDDATE": "geändert am",
53 "UPDNAME": "geändert von"
54 }
55 df.rename(columns=colNames, inplace=True)
56
57 return df
58
59
60def ladeAlleWerkstattauftragPosMengenabweichungen(
61 server: PyAPplus64.APplusServer,
62 cond: Union[PyAPplus64.SqlCondition, str, None] = None) -> pd.DataFrame:
63 sql = PyAPplus64.sql_utils.SqlStatementSelect("WAUFTRAGPOS w")
64 sql.addLeftJoin("personal p", "w.UPDUSER = p.PERSONAL")
65
66 sql.addFieldsTable("w", "ID", "BAUFTRAG", "POSITION", "AG")
67 sql.addFields("(w.MENGE-w.MENGE_IST) as MENGENABWEICHUNG")
68 sql.addFieldsTable("w", "MENGE", "MENGE_IST", "APLAN as ARTIKEL")
69 sql.addFields("w.UPDDATE", "p.NAME as UPDNAME")
70
71 sql.where.addConditionFieldEq("w.STATUS", 4)
72 sql.where.addCondition("abs(w.MENGE-w.MENGE_IST) > 0.001")
73 sql.where.addCondition(cond)
74 sql.order = "w.UPDDATE"
75
76 dfOrg = PyAPplus64.pandas.pandasReadSql(server, sql)
77
78 # Add Links
79 df = dfOrg.copy()
80 df = df.drop(columns=["ID"])
81 df['POSITION'] = PyAPplus64.pandas.mkHyperlinkDataframeColumn(
82 dfOrg,
83 lambda r: r.POSITION,
84 lambda r: server.makeWebLinkWauftrag(
85 bauftrag=r.BAUFTRAG, accessid=r.ID))
86 df['BAUFTRAG'] = PyAPplus64.pandas.mkHyperlinkDataframeColumn(
87 dfOrg,
88 lambda r: r.BAUFTRAG,
89 lambda r: server.makeWebLinkBauftrag(bauftrag=r.BAUFTRAG))
90 df['AG'] = PyAPplus64.pandas.mkHyperlinkDataframeColumn(
91 dfOrg,
92 lambda r: r.AG,
93 lambda r: server.makeWebLinkWauftragPos(
94 bauftrag=r.BAUFTRAG, position=r.POSITION, accessid=r.ID))
95
96 # Demo zum Hinzufügen einer berechneten Spalte
97 # df['BAUFPOSAG'] = PyAPplus64.pandas.mkDataframeColumn(dfOrg,
98 # lambda r: "{}.{} AG {}".format(r.BAUFTRAG, r.POSITION, r.AG))
99
100 # Rename Columns
101 colNames = {
102 "BAUFTRAG": "Betriebsauftrag",
103 "POSITION": "Pos",
104 "AG": "AG",
105 "MENGENABWEICHUNG": "Mengenabweichung",
106 "MENGE": "Menge",
107 "MENGE_IST": "Menge-Ist",
108 "ARTIKEL": "Artikel",
109 "UPDDATE": "geändert am",
110 "UPDNAME": "geändert von"
111 }
112 df.rename(columns=colNames, inplace=True)
113 return df
114
115
116def computeInYearMonthCond(field: str, year: Optional[int] = None,
117 month: Optional[int] = None) -> Optional[PyAPplus64.SqlCondition]:
118 if not (year is None):
119 if month is None:
120 return PyAPplus64.sql_utils.SqlConditionDateTimeFieldInYear(field, year)
121 else:
122 return PyAPplus64.sql_utils.SqlConditionDateTimeFieldInMonth(field, year, month)
123 else:
124 return None
125
126
127def computeFileName(year: Optional[int] = None, month: Optional[int] = None) -> str:
128 if year is None:
129 return 'mengenabweichungen-all.xlsx'
130 else:
131 if month is None:
132 return 'mengenabweichungen-{:04d}.xlsx'.format(year)
133 else:
134 return 'mengenabweichungen-{:04d}-{:02d}.xlsx'.format(year, month)
135
136
137def _exportInternal(server: PyAPplus64.APplusServer, fn: str,
138 cond: Union[PyAPplus64.SqlCondition, str, None]) -> int:
139 df1 = ladeAlleWerkstattauftragMengenabweichungen(server, cond)
140 df2 = ladeAlleWerkstattauftragPosMengenabweichungen(server, cond)
141 print("erzeuge " + fn)
142 PyAPplus64.pandas.exportToExcel(fn, [(df1, "WAuftrag"), (df2, "WAuftrag-Pos")], addTable=True)
143 return len(df1.index) + len(df2.index)
144
145
146def exportVonBis(server: PyAPplus64.APplusServer, fn: str,
147 von: Optional[datetime.datetime], bis: Optional[datetime.datetime]) -> int:
148 cond = PyAPplus64.sql_utils.SqlConditionDateTimeFieldInRange("w.UPDDATE", von, bis)
149 return _exportInternal(server, fn, cond)
150
151
152def exportYearMonth(server: PyAPplus64.APplusServer,
153 year: Optional[int] = None, month: Optional[int] = None) -> int:
154 cond = computeInYearMonthCond("w.UPDDATE", year=year, month=month)
155 fn = computeFileName(year=year, month=month)
156 return _exportInternal(server, fn, cond)
157
158
159def computePreviousMonthYear(cyear: int, cmonth: int) -> Tuple[int, int]:
160 if cmonth == 1:
161 return (cyear-1, 12)
162 else:
163 return (cyear, cmonth-1)
164
165
166def computeNextMonthYear(cyear: int, cmonth: int) -> Tuple[int, int]:
167 if cmonth == 12:
168 return (cyear+1, 1)
169 else:
170 return (cyear, cmonth+1)
171
172
173def main(confFile: Union[str, pathlib.Path], user: Optional[str] = None, env: Optional[str] = None) -> None:
174 server = PyAPplus64.applusFromConfigFile(confFile, user=user, env=env)
175
176 now = datetime.date.today()
177 (cmonth, cyear) = (now.month, now.year)
178 (pyear, pmonth) = computePreviousMonthYear(cyear, cmonth)
179
180 # Ausgaben
181 exportYearMonth(server, cyear, cmonth) # Aktueller Monat
182 exportYearMonth(server, pyear, pmonth) # Vorheriger Monat
183 # export(cyear) # aktuelles Jahr
184 # export(cyear-1) # letztes Jahr
185 # export() # alles
186
187
188if __name__ == "__main__":
189 main(applus_configs.serverConfYamlTest)
mengenabweichung_gui.py
¶
Beispiel für eine sehr einfache GUI, die die Eingabe einfacher Parameter erlaubt. Die GUI wird um die Erzeugung von Excel-Dateien mit Mengenabweichungen gebaut.
1import PySimpleGUI as sg # type: ignore
2import mengenabweichung
3import datetime
4import PyAPplus64
5import applus_configs
6import pathlib
7from typing import Tuple, Optional, Union
8
9
10def parseDate(dateS: str) -> Tuple[Optional[datetime.datetime], bool]:
11 if dateS is None or dateS == '':
12 return (None, True)
13 else:
14 try:
15 return (datetime.datetime.strptime(dateS, '%d.%m.%Y'), True)
16 except:
17 sg.popup_error("Fehler beim Parsen des Datums '{}'".format(dateS))
18 return (None, False)
19
20
21def createFile(server: PyAPplus64.APplusServer, fileS: str, vonS: str, bisS: str) -> None:
22 (von, vonOK) = parseDate(vonS)
23 if not vonOK:
24 return
25
26 (bis, bisOK) = parseDate(bisS)
27 if not bisOK:
28 return
29
30 if (fileS is None) or fileS == '':
31 sg.popup_error("Es wurde keine Ausgabedatei ausgewählt.")
32 return
33 else:
34 file = pathlib.Path(fileS)
35
36 c = mengenabweichung.exportVonBis(server, file.as_posix(), von, bis)
37 sg.popup_ok("{} Datensätze erfolgreich in Datei '{}' geschrieben.".format(c, file))
38
39
40def main(confFile: Union[str, pathlib.Path], user: Optional[str] = None, env: Optional[str] = None) -> None:
41 server = PyAPplus64.applusFromConfigFile(confFile, user=user, env=env)
42
43 layout = [
44 [sg.Text(('Bitte geben Sie an, für welchen Zeitraum die '
45 'Mengenabweichungen ausgegeben werden sollen:'))],
46 [sg.Text('Von (einschließlich)', size=(15, 1)), sg.InputText(key='Von'),
47 sg.CalendarButton("Kalender", close_when_date_chosen=True,
48 target="Von", format='%d.%m.%Y')],
49 [sg.Text('Bis (ausschließlich)', size=(15, 1)), sg.InputText(key='Bis'),
50 sg.CalendarButton("Kalender", close_when_date_chosen=True,
51 target="Bis", format='%d.%m.%Y')],
52 [sg.Text('Ausgabedatei', size=(15, 1)), sg.InputText(key='File'),
53 sg.FileSaveAs(button_text="wählen",
54 target="File",
55 file_types=(('Excel Files', '*.xlsx'),),
56 default_extension=".xlsx")],
57 [sg.Button("Aktueller Monat"), sg.Button("Letzter Monat"),
58 sg.Button("Aktuelles Jahr"), sg.Button("Letztes Jahr")],
59 [sg.Button("Speichern"), sg.Button("Beenden")]
60 ]
61
62 systemName = server.scripttool.getSystemName() + "/" + server.scripttool.getMandant()
63 window = sg.Window("Mengenabweichung " + systemName, layout)
64 now = datetime.date.today()
65 (cmonth, cyear) = (now.month, now.year)
66 (pyear, pmonth) = mengenabweichung.computePreviousMonthYear(cyear, cmonth)
67 (nyear, nmonth) = mengenabweichung.computeNextMonthYear(cyear, cmonth)
68
69 while True:
70 event, values = window.read()
71 if event == sg.WIN_CLOSED or event == 'Beenden':
72 break
73 if event == 'Aktueller Monat':
74 window['Von'].update(value="01.{:02d}.{:04d}".format(cmonth, cyear))
75 window['Bis'].update(value="01.{:02d}.{:04d}".format(nmonth, nyear))
76 if event == 'Letzter Monat':
77 window['Von'].update(value="01.{:02d}.{:04d}".format(pmonth, pyear))
78 window['Bis'].update(value="01.{:02d}.{:04d}".format(cmonth, cyear))
79 if event == 'Aktuelles Jahr':
80 window['Von'].update(value="01.01.{:04d}".format(cyear))
81 window['Bis'].update(value="01.01.{:04d}".format(cyear+1))
82 if event == 'Letztes Jahr':
83 window['Von'].update(value="01.01.{:04d}".format(cyear-1))
84 window['Bis'].update(value="01.01.{:04d}".format(cyear))
85 if event == 'Speichern':
86 try:
87 createFile(server, values.get('File', None),
88 values.get('Von', None), values.get('Bis', None))
89 except Exception as e:
90 sg.popup_error_with_traceback("Beim Erzeugen der Excel-Datei trat ein Fehler auf:", e)
91
92 window.close()
93
94
95if __name__ == "__main__":
96 main(applus_configs.serverConfYamlProd)
complete_sql.pyw
¶
Beispiel, wie ein einfacher APP-Server Aufruf über eine GUI zur Verfügung gestellt und mittels Python-Bibliotheken erweitert werden kann. Zudem wird demonstriert, wie eine Auswahl verschiedenere Systeme und Umgebungen realisiert werden kann.
1import PySimpleGUI as sg # type: ignore
2import PyAPplus64
3import applus_configs
4import pathlib
5from typing import Tuple, Optional, Union
6
7try:
8 import sqlparse
9except:
10 pass
11
12try:
13 import sqlfmt.api
14except:
15 pass
16
17def prettyPrintSQL(format, sql):
18 try:
19 if format == "sqlfmt":
20 mode = sqlfmt.api.Mode(dialect_name="ClickHouse")
21 sqlPretty = sqlfmt.api.format_string(sql, mode)
22 return sqlPretty.replace("N '", "N'") # fix String Constants
23 elif format == "sqlparse-2":
24 return sqlparse.format(sql, reindent=True, keyword_case='upper')
25 elif format == "sqlparse":
26 return sqlparse.format(sql, reindent_aligned=True, keyword_case='upper')
27 else:
28 return sql
29 except e:
30 print (str(e))
31 return sql
32
33def main() -> None:
34 monospaceFont = ("Courier New", 12)
35 sysenvs = applus_configs.serverConfDescs[:];
36 sysenvs.append("-");
37 layout = [
38 [sg.Button("Vervollständigen"), sg.Button("aus Clipboard", key="import"), sg.Button("nach Clipboard", key="export"), sg.Button("zurücksetzen", key="clear"), sg.Button("Beenden"),
39 sg.Text('System/Umgebung:'), sg.Combo(sysenvs, default_value="-", key="sysenv", readonly=True), sg.Text('Formatierung:'), sg.Combo(["-", "sqlfmt", "sqlparse", "sqlparse-2"], default_value="sqlparse", key="formatieren", readonly=True)
40 ],
41 [sg.Text('Eingabe-SQL')],
42 [sg.Multiline(key='input', size=(150, 20), font=monospaceFont)],
43 [sg.Text('Ausgabe-SQL')],
44 [sg.Multiline(key='output', size=(150, 20), font=monospaceFont, horizontal_scroll=True)]
45 ]
46
47 # server = PyAPplus64.applusFromConfigFile(confFile, user=user, env=env)
48 # systemName = server.scripttool.getSystemName() + "/" + server.scripttool.getMandant()
49 window = sg.Window("Complete SQL", layout)
50 oldSys = None
51 while True:
52 event, values = window.read()
53 if event == sg.WIN_CLOSED or event == 'Beenden':
54 break
55 elif event == 'clear':
56 window['input'].update("")
57 window['output'].update("")
58 elif event == 'import':
59 try:
60 window['input'].update(window.TKroot.clipboard_get())
61 except:
62 window['input'].update("")
63 window['output'].update("")
64 elif event == 'export':
65 try:
66 window.TKroot.clipboard_clear()
67 window.TKroot.clipboard_append(window['output'].get())
68 except:
69 pass
70 elif event == 'Vervollständigen':
71 sqlIn = window['input'].get()
72 try:
73 if sqlIn:
74 sys = window['sysenv'].get()
75 if sys != oldSys:
76 oldSys = sys
77 if sys and sys != "-":
78 server = sys.connect()
79 else:
80 server = None
81 if server:
82 sqlOut = server.completeSQL(sqlIn)
83 else:
84 sqlOut = sqlIn
85 sqlOut = prettyPrintSQL(window['formatieren'].get(), sqlOut)
86 else:
87 sqlOut = ""
88 except Exception as e:
89 sqlOut = "ERROR: " + str(e)
90 sg.popup_error_with_traceback("Fehler bei Vervollständigung", e)
91 window['output'].update(value=sqlOut)
92
93 window.close()
94
95
96if __name__ == "__main__":
97 main()
importViewUDF.py
¶
Folgende Scripte erlauben den einfachen Import von DB-Anpass-Dateien, Views und UDFs über den Windows-Explorer.
Werden Verknüpfungen zu den Scripten importViewUDFDeploy.pyw
und importViewUDFTest.pyw
in %appdata%\Microsoft\Windows\SendTo
abgelegt,
so können eine oder mehrerer solcher Dateien mittels _Kontextmenü (Rechtsklick) - Senden an_ an APplus zur Verarbeitung übergeben werden.
Dabei ist es wichtig, dass sich die Dateien im für den jeweiligen Typ passenden Verzeichnis befinden.
1import PySimpleGUI as sg # type: ignore
2import pathlib
3import PyAPplus64
4from PyAPplus64 import applus
5from PyAPplus64 import sql_utils
6import applus_configs
7import traceback
8import pathlib
9import sys
10
11def importViewsUDFs(server, views, udfs, dbanpass):
12 res = ""
13 try:
14 if views or udfs:
15 for env in server.scripttool.getAllEnvironments():
16 res = res + server.importUdfsAndViews(env, views, udfs);
17 res = res + "\n\n";
18
19 for xml in dbanpass:
20 res = res + "Verarbeite " + xml + "\n"
21 xmlRes = server.updateDatabase(xml);
22 if (xmlRes == ""): xmlRes = "OK";
23 res = res + xmlRes
24 res = res + "\n\n"
25
26 sg.popup_scrolled("Importiere", res)
27 except:
28 sg.popup_error("Fehler", traceback.format_exc())
29
30def importIntoSystem(server, system):
31 try:
32 if (len(sys.argv) < 2):
33 sg.popup_error("Keine Datei zum Import übergeben")
34 return
35
36 views = []
37 udfs = []
38 dbanpass = []
39 errors = ""
40
41
42 for i in range (1, len(sys.argv)):
43 arg = pathlib.Path(sys.argv[i])
44 if arg == server.scripttool.getInstallPathAppServer().joinpath("Database", "View", arg.stem + ".sql"):
45 views.append(arg.stem)
46 elif arg == server.scripttool.getInstallPathAppServer().joinpath("Database", "UDF", arg.stem + ".sql"):
47 udfs.append(arg.stem)
48 elif arg == server.scripttool.getInstallPathAppServer().joinpath("DBChange", arg.stem + ".xml"):
49 dbanpass.append(arg.stem + ".xml")
50 else:
51 errors = errors + " - " + str(arg) + "\n";
52
53 if len(errors) > 0:
54 msg = "Folgende Dateien sind keine View, UDF oder DB-Anpass-Dateien des "+system+"-Systems:\n" + errors;
55 sg.popup_error("Fehler", msg);
56 if views or udfs or dbanpass:
57 importViewsUDFs(server, views, udfs, dbanpass)
58
59 except:
60 sg.popup_error("Fehler", traceback.format_exc())
61
62if __name__ == "__main__":
63 server = PyAPplus64.applusFromConfigFile(applus_configs.serverConfYamlDeploy)
64 importIntoSystem(server, "Deploy");
65
66
67
Wrapper für Deploy-System:
1import importViewUDF
2import applus_configs
3import PyAPplus64
4
5if __name__ == "__main__":
6 server = PyAPplus64.applusFromConfigFile(applus_configs.serverConfYamlDeploy)
7 importViewUDF.importIntoSystem(server, "Deploy")
Wrapper für Test-System:
1import importViewUDF
2import applus_configs
3import PyAPplus64
4
5if __name__ == "__main__":
6 server = PyAPplus64.applusFromConfigFile(applus_configs.serverConfYamlTest)
7 importViewUDF.importIntoSystem(server, "Test")
copy_artikel.py
¶
Beispiel, wie Artikel inklusive Arbeitsplan und Stückliste dupliziert werden kann.
1import pathlib
2import PyAPplus64
3import applus_configs
4import logging
5import yaml
6from typing import Optional
7
8
9def main(confFile: pathlib.Path, artikel: str, artikelNeu: Optional[str] = None) -> None:
10 # Server verbinden
11 server = PyAPplus64.applus.applusFromConfigFile(confFile)
12
13 # DuplicateBusinessObject für Artikel erstellen
14 dArt = PyAPplus64.duplicate.loadDBDuplicateArtikel(server, artikel)
15
16 # DuplicateBusinessObject zur Demonstration in YAML konvertieren und zurück
17 dArtYaml = yaml.dump(dArt)
18 print(dArtYaml)
19 dArt2 = yaml.load(dArtYaml, Loader=yaml.UnsafeLoader)
20
21 # Neue Artikel-Nummer bestimmen und DuplicateBusinessObject in DB schreiben
22 # Man könnte hier genauso gut einen anderen Server verwenden
23 if (artikelNeu is None):
24 artikelNeu = server.nextNumber("Artikel")
25
26 if not (dArt is None):
27 dArt.setFields({"artikel": artikelNeu})
28 res = dArt.insert(server)
29 print(res)
30
31
32if __name__ == "__main__":
33 # Logger Einrichten
34 logging.basicConfig(level=logging.INFO)
35 # logger = logging.getLogger("PyAPplus64.applus_db");
36 # logger.setLevel(logging.ERROR)
37
38 main(applus_configs.serverConfYamlTest, "my-artikel", artikelNeu="my-artikel-copy")