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:
+156
-39
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user