In 'manage_configs.py' Klasse 'SivasAssemblyData' in 'SivasBOM' und Klasse 'TeilestammMetadata' in 'SivasTeilestamm' umbenannt, da eindeutiger. In 'controller.py' Namen entsprechend aktualisiert. Zudem in 'manage_configs.py' Klasse 'SivasBOM' die Methode 'asm_data' in 'bom_data' umbenannt. Darüber hinaus gibt die Methode nun ein leeres Dict zurück, wenn keine JSON vorliegt oder keine generiert werden konnte. Dies wurde vorgesehen, um im Migrationsüberblick (Treeview) sowie dem Migrationstool (CreoMigrate) auch Teilenummern ohne Stückliste, d.h. ohne JSON abbilden zu können (genaue Funktionsweise siehe mehrzeiliger Kommentar in genannter Methode). Abgesehen davon Methode 'property_names' komplett entfernt, da diese fehlerhaft funktioniert hat, da jedes Mal durch alle Kinder der Assembly geloopt wurde und die Eigenschaften des aktuellen Kindes wie z.B. 'Bezeichnung', 'Parent', etc. ausgelesen wurden. Der Fehler liegt darin, dass die Eigenschaften der Nummer aus der vorherigen Iteration komplett überschrieben, aber nicht ergänzt wurden, falls in der aktuellen Iteration Eigenschaften vorliegen, die in der vorherigen noch nicht vorlagen. Um dieses Problem ganz zu umgehen, wurden die Methoden 'get_prop_val_for_all_ids' und 'all_bom_properties' umgeschrieben, sodass die Eigenschaften direkt innerhalb dieser Funktionen geholt werden

This commit is contained in:
2025-04-20 12:05:46 +02:00
parent 56ff5010c7
commit 623f4a12e1
2 changed files with 74 additions and 73 deletions
+2 -2
View File
@@ -2,7 +2,7 @@ import os
from tkinter import messagebox
import update_database
from manage_configs import SivasAssemblyData, RuleDesignerDatabaseConfig, MigrationStatus
from manage_configs import SivasBOM, RuleDesignerDatabaseConfig, MigrationStatus
"""
Contains the logic for the MVC of CreoMigrate Gui
@@ -120,7 +120,7 @@ class Controller(Observer):
data_dir = self.get_env("data")
rd_dbase_filename = self.get_env("rd_dbase_filename")
asm_data = SivasAssemblyData(data_dir, asm_id + '.json', load_local_asm_json)
asm_data = SivasBOM(data_dir, asm_id + '.json', load_local_asm_json)
rd_data = RuleDesignerDatabaseConfig(data_dir, rd_dbase_filename, load_local_rd_dbase)
migration_status = MigrationStatus(asm_data.child_ids, rd_data.ids)
+66 -65
View File
@@ -19,12 +19,9 @@ class JsonBasedConfig:
def load_json_from_file(self):
"""lade das json file vom gegeben Pfad in ein json Objekt"""
try:
with open(self._config_path, 'r', encoding='utf-8') as fh:
content = fh.read()
return json.loads(content)
except FileNotFoundError:
raise ValueError("Bitte prüfen, ob korrekte Teilenummer, bzw. korrekter Dateiname angegeben wurde.")
def from_json(self, json_str):
"""nimm den Json String zur Initialisierung des Objektes"""
@@ -99,45 +96,63 @@ class RuleDesignerSQLData(SQLBasedConfig):
return self._rd_statuses
class SivasAssemblyData(JsonBasedConfig):
class SivasBOM(JsonBasedConfig):
"""Auslesen der Assembly-Informationen zu einer angegebenen Baugruppennummer"""
def __init__(self, config_dir: str, config_file: str, load_local_json=False):
super().__init__(config_dir, config_file)
self._load_local_json = load_local_json
self._asm_data = None
self._bom_data = None
self._child_ids = None
self._parent_children = None
self._longest_child_id = None
self._max_bom_depth = None
self._property_names = None
self._all_bom_properties = None
def create_asm_json(self):
def create_asm_json(self) -> bool:
"""Erstellt JSON mit den aktuellen Baugruppeninformationen"""
try:
update_database.get_sivas_bom(self._config_file.removesuffix(".json"))
except:
raise ValueError("JSON-Datei mit Baugruppeninformationen konnte nicht erstellt werden!")
@property
def asm_data(self) -> dict:
"""Liest die Baugruppen-JSON ein und gibt deren Informationen zurück"""
if self._asm_data is None:
def bom_data(self) -> dict:
""" Liest die JSON-Datei der Baugruppenstückliste ein und speichert die Informationen als dict. """
if self._bom_data is None:
"""
Falls die JSON nicht existiert oder nicht generiert werden kann, soll die Möglichkeit bestehen,
diese eigenständig zu erweitern, da in der JSON z.B. die Nummer der obersten Baugruppe standardmäßig
nicht vorliegt. Generierungs- und Einlese-Fehler werden daher bewusst ignoriert, um stattdessen ein leeres
dict zurückzugeben, das anschließend erweitert werden kann.
Die Möglichkeit zur Erweiterung der Stückliste ermöglicht es zudem, Teilenummern ohne Stückliste abzubilden.
Das funktioniert, indem man die Teilenummer ohne eigene Stückliste als Kind einer fiktiven Baugruppe "None"
ansieht / definiert. Dadurch ist keine separate Logik erforderlich, die sich nur mit Teilenummern
ohne Stückliste befasst.
"""
self._bom_data = {}
if not self._load_local_json:
try:
self.create_asm_json()
except ValueError:
pass
try:
self._bom_data = self.load_json_from_file()
except FileNotFoundError:
pass
self._asm_data = self.load_json_from_file()
return self._asm_data
return self._bom_data
@property
def child_ids(self) -> set:
"""Gibt alle Teilenummern der Stückliste zurück (auch Teilenummern aus tieferen Baugruppenebenen)"""
if self._child_ids is None:
self._child_ids = set(self.asm_data.keys())
self._child_ids = set(self.bom_data.keys())
return self._child_ids
@property
@@ -147,7 +162,7 @@ class SivasAssemblyData(JsonBasedConfig):
if self._parent_children is None:
unordered_parent_children = {}
for child_id, parent_properties in self.asm_data.items():
for child_id, parent_properties in self.bom_data.items():
for parent_property in parent_properties:
parent_id = parent_property["Parent"]
child_posnr_in_parent_bom = int(parent_property["Position"].lstrip(".").split("/")[0])
@@ -180,20 +195,11 @@ class SivasAssemblyData(JsonBasedConfig):
]
}"""
if id not in self.bom_data:
self._bom_data[id] = []
property_names = self.property_names
asm_data = self.asm_data
if id not in asm_data:
self._asm_data[id] = []
for property_name in property_names:
if property_name not in metadata:
metadata[property_name] = None
self._asm_data[id].append(metadata)
return self._asm_data
self._bom_data[id].append(metadata)
return self._bom_data
@property
def longest_child_id(self) -> str:
@@ -209,44 +215,32 @@ class SivasAssemblyData(JsonBasedConfig):
if self._max_bom_depth is None:
bom_levels = []
for parents in self.asm_data.values():
for parents in self.bom_data.values():
for parent in parents:
current_bom_level = parent["Position"].count(".")
bom_levels.append(current_bom_level)
self._max_bom_depth = max(bom_levels)
return self._max_bom_depth
@property
def property_names(self) -> list:
"""Gibt alle Eigenschaftsnamen zurück, die in der Assembly-json-Datei enthalten sind"""
if self._property_names is None:
for parent_data in self.asm_data.values():
self._property_names = list(parent_data[0])
return self._property_names
def get_prop_val_for_single_id(self, id:str, property_name:str) -> str:
"""Gibt eine Eigenschaft von einer einzelnen Teilenummer aus der Stückliste zurück"""
if id not in self._asm_data:
raise KeyError("Angegebene Teilenummer befindet sich nicht in der Baugruppe!")
if id not in self._bom_data:
raise ValueError("Teilenummer befindet sich nicht in der Baugruppe!")
if property_name not in self._asm_data[id][0]:
raise ValueError(f"Teilenummer besitzt nicht die angegebene Eigenschaft '{property_name}'")
if property_name not in self._bom_data[id][0]:
return
return self._asm_data[id][0][property_name]
return self._bom_data[id][0][property_name]
def get_prop_val_for_all_ids(self, property_name) -> dict:
"""Gibt eine Eigenschaft zu allen Teilenummern der Stückliste zurück (z.B. Bezeichnung)"""
if property_name not in self.property_names:
raise ValueError("Angegebener Eigenschaftsname exisitert nicht!")
id_property_mapping = {}
for child, parent_data in self.asm_data.items():
for properties in parent_data:
if property_name in properties:
id_property_mapping[child] = properties[property_name]
for child_id, asm_usages in self.bom_data.items():
child_properties = asm_usages[0]
id_property_mapping[child_id] = None if property_name not in child_properties else child_properties[property_name]
return id_property_mapping
@property
@@ -254,9 +248,16 @@ class SivasAssemblyData(JsonBasedConfig):
"""Gibt alle Eigenschaften zu den Teilenummern der Stückliste zurück (z.B. Bezeichnung)"""
if self._all_bom_properties is None:
self._all_bom_properties = {}
for property_name in self.property_names:
self._all_bom_properties[property_name] = self.get_prop_val_for_all_ids(property_name)
for child_id, asm_usages in self.bom_data.items():
child_properties = asm_usages[0]
for property_name, property_val in child_properties.items():
if property_name not in self._all_bom_properties:
self._all_bom_properties[property_name] = {}
self._all_bom_properties[property_name][child_id] = property_val
return self._all_bom_properties
@@ -338,34 +339,34 @@ class MigrationStatus:
return self._ids_pending
class TeilestammMetadata(CSVBasedConfig):
class SivasTeilestamm(CSVBasedConfig):
def __init__(self, config_dir, config_file, load_local_csv=False):
super().__init__(config_dir, config_file)
self._load_local_csv = load_local_csv
self._csv_data = None
self._data = None
@staticmethod
def create_csvs(ids):
"""Erstellt CSV-Datei(en) mit den Teilestamminformationen zu der / den angegebenen Teilenummer(n)"""
try:
update_database.get_sivas_teilestamm(ids)
except:
raise ValueError("CSV(s) konnte nicht generiert werden!")
@property
def csv_data(self):
def teilestamm_data(self):
"""Gibt CSV-Daten als Dataframe zurück"""
if self._csv_data is None:
if self._data is None:
if not self._load_local_csv:
self.create_csvs(self._config_file.removesuffix(".csv"))
self._csv_data = self.load_csv_from_file()
return self._csv_data
self._data = self.load_csv_from_file()
return self._data
def get_property_values(self, property_name) -> str:
"""Gibt Wert aus der CSV für den angegebenen Spaltennamen zurück"""
ret = self.csv_data[property_name][0]
ret = self.teilestamm_data[property_name][0]
return ret