Erste Fassung einer Treeview-Darstellung der zu migrierenden Teile (aktuell ohne Kommentarspalte) erstellt, um einen schnellen Überblick über den ausstehenden Migrationsaufwand zu erhalten + Automatische Erstellung des Work-Ordners bei Excel-Export ergänz, da dieser nicht leer ohne workarounds in git eingecheckt werden kann und sonst bei erstem Excel-Export eine Fehlermeldung erscheint

This commit is contained in:
2023-11-01 22:35:38 +01:00
parent 5e401e0d50
commit 58c52d0a97
+156 -39
View File
@@ -45,21 +45,18 @@ def create_excel_export(existingIds, sivasData, sivasId, outPath):
sortierung.append(create_sorter_string(sivasData, item))
teilenummer.append(item)
bezeichnung.append(sivasData[item]['Bezeichnung'])
if existingIds[item] is True:
existing = "VERFÜGBAR"
else:
existing = "IMPORTIEREN"
existing = "VERFÜGBAR" if existingIds[item] is True else False
migrationsstatus.append(existing)
teilebeurteilung.append('')
zusatzbemerkung.append('')
data = {
"Sortierung":sortierung,
"Teilenummer":teilenummer,
"Bezeichnung":bezeichnung,
"Migrationsstatus":migrationsstatus,
"Teile Beurteilung":teilebeurteilung,
"Zusatzbemerkung":zusatzbemerkung
"Sortierung": sortierung,
"Teilenummer": teilenummer,
"Bezeichnung": bezeichnung,
"Migrationsstatus": migrationsstatus,
"Teile Beurteilung": teilebeurteilung,
"Zusatzbemerkung": zusatzbemerkung
}
excel_filename = os.path.join(outPath, sivasId + ".xlsx")
@@ -67,50 +64,170 @@ def create_excel_export(existingIds, sivasData, sivasId, outPath):
df.to_excel(excel_filename, sheet_name="Ergebnis", index_label="Sortierung")
def compareFiles(rdDataBasePath, jsonPath, sivasId, outPath):
# Lies die CSV-Datei ein, in der alle RuleDesigner-Nummern aufgelistet sind ein
def read_sivas_nums(jsonPath):
with open(jsonPath, encoding='utf-8') as json_file:
return json.load(json_file)
def read_ruledesigner_nums(rdDataBasePath):
df = pd.read_csv(rdDataBasePath, sep=';', converters={"Teilenummer":str})
tn = tuple(df["Teilenummer"])
# Lies die JSON-Datei ein, in der alle Sivas-Teilenummern aufgelistet sind, die in Verbindung mit der Migration einer Teilenummer ebenfalls migriert werden müssen
with open(jsonPath, encoding='utf-8') as fp:
sivasData = json.load(fp)
return tuple(df["Teilenummer"])
# Prüfe, ob die Sivas-Nummern bereits migriert wurden
def compareFiles(rdDataBasePath, jsonPath, sivasId, outPath):
# Liest:
# - die CSV-Datei ein, in der alle RuleDesigner-Nummern aufgelistet sind
# - die JSON-Datei ein, in der alle Sivas-Teilenummern, die i.V.m einer Teilenummer ebenfalls migriert werden müssen
ruledesigner_ids = read_ruledesigner_nums(rdDataBasePath)
sivas_ids = read_sivas_nums(jsonPath)
# Prüft, ob die Sivas-Nummern bereits migriert wurden
existingIds = {}
for item in sivasData:
if item in tn:
existingIds[item] = True
else:
existingIds[item] = False
for sivas_id in sivas_ids:
existingIds[sivas_id] = True if sivas_id in ruledesigner_ids else False
# Schreibe eine Excel-Datei mit den korrekten Spalten raus
create_excel_export(existingIds, sivasData, sivasId, outPath)
# Erstellt das work-Verzeichnis, falls dieses noch nicht exisitert
if not os.path.isdir(outPath):
print(f"Fehlendes work-Verzeichnis unter '{outPath}' erstellt")
os.mkdir(outPath)
# Schreibt eine Excel-Datei mit den korrekten Spalten raus
create_excel_export(existingIds, sivas_ids, sivasId, outPath)
def compare_treeview(json_path, ruledesigner_path):
ruledesigner_nums = read_ruledesigner_nums(ruledesigner_path)
sivas_nums = read_sivas_nums(json_path)
# Verbinder-Symbole
symbols = {
"pipe": "",
"empty": " ",
"elbow": "└──",
"t": "├──"
}
# ANSI-Escape-Sequenzen für Einfärbung des Terminals abhängig vom Migrationsstatus.
# Codes, siehe https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797
# BG = Hintergrundfarbe
colors = {
"BG_RED": "\033[41m",
"BG_GREEN": "\033[42m",
"RESET": "\033[0m"
}
prefix = ""
# Erstellt dict mit allen Parents (Keys) und weist den Parents deren Kinder als Werte zu.
# Wird später benötigt, um zu bestimmen, ob eine Teilenummer das letzte Kind eines Parents ist d.h. wenn ein Parent z.B. 4 Kinder
# besitzt, ob es sich um das letzte, also 4. Kind handelt. In diesem Fall darf unter der Nummer kein Pipe-Symbol erscheinen
parents_children = {}
for sivas_num in sivas_nums:
parent = sivas_nums[sivas_num]["Parent"]
if parent not in parents_children:
parents_children[parent] = []
parents_children[parent].append(sivas_num)
max_tree_depth = max(i["Position"].count(".") for i in sivas_nums.values())
# Längste Sivas-Teilenummer (weil evtl. >9, wenn mit Underline)
max_sivas_num_len = max([len(i) for i in sivas_nums.keys()])
max_description_len = max([len(i["Bezeichnung"]) for i in sivas_nums.values()])
# Erstellung des Treeviews mit Spalte "Bezeichnung"
for i, sivas_num in enumerate(sivas_nums):
# Für Verarbeitung der ANSI-Escape-Sequenzen,
# siehe https://stackoverflow.com/questions/12492810/python-how-can-i-make-the-ansi-escape-codes-to-work-also-in-windows
os.system("color")
parent = sivas_nums[sivas_num]["Parent"]
description = sivas_nums[sivas_num]["Bezeichnung"]
position = sivas_nums[sivas_num]["Position"]
# Wird später für Zusammensetzung des Präfix benötigt
if (i + 1) != len(sivas_nums):
next_key = list(sivas_nums)[i + 1]
next_key_pos = sivas_nums[next_key]["Position"]
# Ermittelt das Level des aktuellen und nächsten Keys bezogen auf die Nummern-Hierarchie
current_key_level = position.count(".")
next_key_level = next_key_pos.count(".")
# └── als Verbinder, wenn letzter Knotenpunkt, sonst ├──
connector_symbol = symbols['elbow'] if sivas_num == parents_children[parent][-1] else symbols['t']
# Farbliche Terminal-Darstellung abhängig vom Migrationsstatus: grün = migriert, rot = noch nicht migriert
output_color = f"{colors['BG_GREEN']}" if sivas_num in ruledesigner_nums else f"{colors['BG_RED']}"
# Bei oberster Teilenummer soll kein Verbinder dargestellt werden.
if i == 0:
print(f"{output_color}{parent}{colors['RESET']}")
tree_str = f"{prefix}{connector_symbol}{output_color}{sivas_num}{colors['RESET']}"
len_tree_str = len(tree_str) - len(output_color) - len(colors['RESET'])
# Anzahl der Leerzeichen zwischen dem Tree und der Bezeichnungsspalte
pad_tree = ((max_tree_depth * len(symbols['pipe']) + len(symbols['t']) + max_sivas_num_len) - len_tree_str + 2) * " "
# Anzahl der Leerzeichen zwischen dem Tree und der Kommentarspalte
pad_description = (max_description_len - len(description) + 2) * " "
print(f"{tree_str}{pad_tree}{description}{pad_description}")
# Nachfolgend wird der Präfix vor der Nummer für den NÄCHSTEN Durchlauf zusammengesetzt
# Der Präfix-Teil setzt sich fallabhängig aus Pipe-Symbolen (| ) und/oder Leerraum ( ) zusammen.
# Prüft, ob die aktuelle Nummer das letzte Kind des Parents ist
if sivas_num == parents_children[parent][-1]:
# Prüft, ob das aktuelle Teil auch ein Parent ist.
# Wenn ja, muss unter dem connector-Symbol der aktuellen Nummer (also im nächsten Durchlauf) Leerraum sein
if sivas_num in parents_children:
prefix += symbols["empty"]
# Baumende auf der aktuellen Ebene ist erreicht. Die nächste Teilenummer (wenn nicht das Gesamtende des Baums erreicht ist)
# liegt unter der aktuellen Ebene. Der bisherige Präfix-String muss folglich gekürzt werden. Die Anzahl der Zeichen,
# die gekürzt werden müssen ergibt sich durch die Anzahl der Ebenen, die zwischen der aktuellen Teilenummer und der darauffolgenden Teilenummer
# liegen und der Länge des Pipe-Symbols, bzw. eines anderen Symbols (alle haben eine Länge von 3)
else:
prefix_trim_len = (next_key_level - current_key_level) * len(symbols["pipe"])
prefix = prefix[:prefix_trim_len]
else:
# Prüft erneut, ob das aktuelle Teil auch ein Parent ist.
# Wenn ja, muss dieses Mal unter der nächsten Nummer ein Pipe-Symbol kommen
if sivas_num in parents_children:
prefix += symbols["pipe"]
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='fetches data from sivas or ruledesigner fusion', prog='update_database')
parser.add_argument('-n', '--number', action='store', help='SIVAS-Number')
parser.add_argument('-s', '--sivas', action='store', help='fetch data of this id from sivas fo local database folder')
parser.add_argument('-d', '--database', action='store', default="RD_Bestandspool.csv", help='local filename of the latest fetched RuleDesigner Database')
parser.add_argument('-t', '--tree', action='store_true', help='displays partnumber hierarchy for given part number in flag -s as treeview. green = migrated, red = not yet migrated')
args = parser.parse_args()
# fetching the names of all existing cad files from the local file
dataDir = os.environ.get('CREMIG_DATA')
rdDataBasePath = os.path.join(dataDir, args.database)
# get the path to ask for further json files
exePath = os.environ.get('SIVAS_DATABASE_QUERY')
# in case the infos for this cad file are already there
sivasId = str(args.sivas)
jsonPath = os.path.join(dataDir, sivasId + ".json")
# there the results are written
outPath = os.environ.get('CREMIG_WORK')
sivas_id = str(args.number)
json_path = os.path.join(dataDir, sivas_id + ".json")
if args.sivas:
# fetching the names of all existing cad files from the local file
dataDir = os.environ.get('CREMIG_DATA')
rdDataBasePath = os.path.join(dataDir, args.database)
# get the path to ask for further json files
exePath = os.environ.get('SIVAS_DATABASE_QUERY')
# in case the infos for this cad file are already there
sivasId = str(args.sivas)
jsonPath = os.path.join(dataDir, sivasId + ".json")
# there the results are written
outPath = os.environ.get('CREMIG_WORK')
compareFiles(rdDataBasePath, jsonPath, sivasId, outPath)
if args.tree:
compare_treeview(json_path, rdDataBasePath)