Compare commits

..

257 Commits

Author SHA1 Message Date
m.stangl b2127b70c9 Add CLAUDE.md for Claude Code guidance
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-11 23:20:21 +02:00
Benjamin_Mueller db46c38ac6 Werkstoff CC493K - GC hinzugefügt 2026-05-05 17:20:01 +02:00
Benjamin_Mueller af69b98365 Materialübersetzung für Ck60 hinzugefügt 2026-05-05 15:48:52 +02:00
Benjamin_Mueller 87ff81d001 Werkstoff 1.1221 (C60E) hinzugefügt 2026-05-05 14:27:10 +02:00
Benjamin_Mueller cbc2afa9e1 Redundante Werkstoffübersetzung hinzugefügt 2026-02-11 09:30:14 +01:00
Benjamin_Mueller 47e70d952e Werkstoff & redundante Werkstoffübersetzung hinzugefügt 2026-02-10 13:03:09 +01:00
Benjamin_Mueller 5a1fa5a7e4 Installationsvoraussetzung erstellt 2026-02-10 11:20:24 +01:00
Benjamin_Mueller 4defeb11f0 Neue Farbausprägung hinzugefügt 2026-02-10 11:17:49 +01:00
Benjamin_Mueller 2591d78716 Installationsvoraussetzung hinzugefügt. Excel in 64 Bit zwingend erforderlich. 32 Bit ist nicht ausreichend 2026-01-08 09:04:45 +01:00
Benjamin_Mueller ac99ca73a5 Farbe Transparent hinzugefügt 2025-11-05 10:17:55 +01:00
Benjamin_Mueller 17cbd61fb4 Werkstoff PVC-P (weich) hinzugefügt) 2025-11-05 10:11:03 +01:00
Benjamin_Mueller f18f8cae2d Materialübersetzung für 1.4301 hinzugefügt und die verschiedenen Übersetzungen zueinander geordnet. 2025-10-30 11:21:39 +01:00
Benjamin_Mueller 7fb778125b Werkstoff hinzugefügt 2025-10-23 10:53:07 +02:00
Benjamin_Mueller a279c581e3 Weitere Rohteilnummer hinzugefügt 2025-10-16 12:30:35 +02:00
Benjamin_Mueller aa73ffb444 Verschiedene Werkstoffe der Auswahlliste hinzugefügt 2025-10-16 12:26:57 +02:00
s.steuer 61cd933de3 FIX - Bei Definierung der automatischen Zusatzinformationen muss geprüft werden, ob die aktuell ausgewählte Nummer über eine Stückliste verfügt. Die Methode 'has_bom', die dafür implementiert wurde hat jedoch nur zurückgegeben, ob die oberste Nummer, nach der gesucht wurde eine Stückliste hat oder nicht. Dies wurde nun behoben, indem zunächst alle Kinder der ausgewählten Nummer geholt werden. Wenn diese 'None' sind hat die ausgewählte Teilenummer keine Stückliste. Die Methode 'has_bom' sowie die Methode 'set_bom_existance' werden daher nun nicht mehr benötigt. Alle entsprechenden Referenzen wurden entfernt. 2025-08-27 16:54:04 +02:00
Benjamin_Mueller 9ef23a735a Werkstoff 'PE-UHMW antistatisch' wurde hinzugefügt 2025-07-29 10:28:16 +02:00
s.steuer 089dadd52b FIX - Wurde der Radiobutton 'Schulung' ausgewählt und anschließend ein weiteres Feld geändert (z.B. Kategorie), dann wurde immer wieder zurück auf den 'Produktiv'-Radiobutton umgeschaltet. Die neu ergänzte Callback-Funktion 'cb_datenbank_neu' verhindert dies nun, d.h. der gewählte Wert (z.B. Schulung) bleibt so lange erhalten, bis ein anderes Teil migriert wird. Defaultwert ist und bleibt weiterhin 'Produktiv' 2025-07-27 22:15:50 +02:00
s.steuer 9f5f4150f1 FIX - fehlenden Backslash nach C:\Users\s.steuer\Documents\Pythonprojekte\CreoMigrate\bin ergänzt, da in cremig_setenv.bat die Umgebungsvariable CREMIG_BIN am Ende ohne Backslash definiert ist 2025-07-26 22:22:05 +02:00
s.steuer c64327cbe7 FIX - Beistellungs- und Dispoaktiv-Eigenschaft darf nur dann eingelesen werden, wenn auch eine Stückliste vorliegt, da andernfalls auch keine JSON vorliegt, aus der die Eigenschaften gelesen werden könnten. Aktuell wurde in diesem Fall eine Fehlermeldung ausgegeben 2025-07-26 20:56:27 +02:00
s.steuer 9e25ca15bc FIX - Backslashes durch noramle Slashes ersetzt, da '\R' = Carriage Return, wodurch eine Syntaxwarnung ausgegeben wird 2025-07-26 20:43:40 +02:00
s.steuer 754ae39364 FIX - Bei der Ermittlung, ob sich Lieferantenbeistellungen oder dispoinaktive Teile in der Stückliste befinden wurden auch die Teilenummern aus tieferen Stücklistenebenen betrachtet. Es dürfen aber nur die Teilenummern der aktiven Stücklistenebene in Betracht gezogen werden. Dies wurde behoben. 2025-07-24 13:30:51 +02:00
s.steuer 6590674d8e FIX - '- BG' aus SE-Eigenschaft 'Title' entfernt, da ' - BG' laut Entscheidung von Hr. Rost nicht mehr in der Baugruppenbezeichnung stehen darf. Im Feld 'Bezeichnung 4' wurde zudem das anfängliche Leerzeichen vor dem Strich in ' - BG' entfernt, da Bezeichnung 4 jetzt auf der Zeichnungsstückliste in der Spalte 'Bemerkung' abgerufen wird und ein Großteil der Baugruppen im System kein Leerzeichen vor dem Strich hat (bei allen 2er-Nummern und bei den Baugruppen, die noch mit der Excel migriert wurden). 2025-07-24 11:34:15 +02:00
s.steuer 6c31b9fbf3 siehe JIRA SUR-645 - Fehlendes Leerzeichen bei Ersetzung von Semikola in den Feldern 'Änderungstext' und 'Freigabevermerk' ergänzt / Logik der Feldprüfung hinsichtlich unzulässigen Zeichen überarbeitet. Konkret werden nun nicht mehr die Werte in der Spalte 'SIVAS-Werte' geprüft, wenn zusätzlich Eintragungen in der Spalte 'Überschriebene Werte' vorliegen / Ergänzend zu SUR-645 folgende Korrektur vorgenommen: Der korrigierte Text im Feld 'Freigabevermerk' (wenn Semikola im SIVAS-Text vorlagen) wurde bisher wieder gelöscht, sobald eine PDM-Kategorie ausgewählt wurde. Diese Löschung erfolgt nun nicht mehr, d.h. der überschriebene Text liegt nun auch nach Wahl der Kategorie weiterhin vor 2025-07-13 18:11:28 +02:00
s.steuer f5cc53253e siehe JIRA SUR-644 - Fehlt eine Nummer in der Blacklist wird nun bei jedem Klick auf 'Migrieren' in der GUI geprüft, ob die Nummer in der ERP_BOM.ini vorliegt. Fehlt sie, erscheint wie gewohnt die Fehlermeldung, dass die Nummer in der Datei fehlt - eine Migration erfolgt also nicht. Erst wenn die Meldung mit 'OK' bestätigt und die Nummer anschließend in die .ini-Datei hinzugefügt wurde kann die Migration mit dem nächsten Klick auf 'Migrieren' erfolgreich abgeschlossen werden. 2025-07-11 23:35:44 +02:00
s.steuer cf4b632cba Logik des Feldes 'Zusatzinformationen automatisch' überarbeitet. Konkret wurde die Erkennung der Fälle überarbeitet, bei denen Zusatzinformationen ausgegeben werden sollen. Es wird nun zunächst geprüft, ob die verschiedenen Einzelfälle, z.B. ob es sich um eine Trümmerbaugruppe handelt, auf die zu migrierende Nummer zutreffen. Ist dies der Fall wird der 'Treffer' gesammelt. Am Ende werden alle Treffer miteinander zu einem String kombiniert. Dieser kombinierte String wird anschließend in der 'Zusatzinformationen.cfg' gesucht. Bei Übereinstimmung wird der zugehörige Text aus der 'Zusatzinformationen.cfg' in das GUI-Textfeld geschrieben. Die Überarbeitung wurde durchgeführt, weil es immer mehr Fälle wurden und es mit der bisherigen Logik unübersichtlich wurde, wo der neue Fall eingefügt werden soll. Zudem entstanden Redundanzen. Die neue Logik sollte deutlich dynamischer, wartbarer und einfacher erweiterbar als die bisherige Variante sein. Es muss jedoch in der Zusatzinformationen.cfg darauf geachtet werden, dass die Optionen korrekt geschrieben werden, da das Programm sonst keine Übereinstimmung finden kann 2025-07-11 22:28:54 +02:00
s.steuer 95fb80dd57 Zeichenbegrenzung auf 45 Zeichen bei Baugruppen und Schweißbaugruppen wird nicht mehr benötigt, da Suffix '- BG' gem. Anordnung GF nicht mehr in Bezeichnungen vorliegen darf. 2025-07-11 16:38:13 +02:00
Benjamin_Mueller b7fd1da5b8 Folgende Änderungen wurden vorgenommen: cremig_setenv.bat wurde so modifiziert, das ein dynamischer Pfadwechsel des Tools 'DataPrepUtility' möglich ist nach einem Solid Edge Versionswechsels. controller.py Fehlermeldung über nicht gefundenen Pfad wurde verfeinert, war zu ungenau. Näheres zu den Änderungen siehe JIRA SUR-648 2025-06-26 16:32:44 +02:00
Benjamin_Mueller e342ace5c3 FIX - Korrektur der Pfadangaben um verwechslung mit Syntaxbefehlen zu vermeiden 2025-06-25 12:07:19 +02:00
Benjamin_Mueller fb710b73e0 Infromationstext des Fensters 'Fehlend in Blacklist' um Pfadangabe der Blacklist und bitte um Programmneustart ergänzt 2025-06-25 09:59:21 +02:00
s.steuer c813a8fc1b FIX - Werkstoffbezeichnungen aus SIVAS, die mit einer Dezimalzahl, wie z.B. '1.4301' oder '1.4305' wurden als float-Werte eingelesen. Die Werte aus der Materialübersetzung.json wurden wiederum als Strings behandelt, dadurch konnte keine Übereinstimmung gefunden werden. Zukünftig werden alle Werkstoffe aus der CSV als String eingelesen 2025-06-23 16:13:40 +02:00
s.steuer f8b895cec7 In 'update_database.py' Namen korrigiert + In 02_get_sivas_dbase.bat Aufruf des fehlenden Schalters ergänzt 2025-06-04 15:51:42 +02:00
Benjamin_Mueller cb20f31f10 Werkstoff Murtfeldt Original 'S' grün der Werkstoff.cfg hinzugefügt 2025-06-03 11:42:38 +02:00
Benjamin_Mueller a6a7d9c3e9 Auswahlmöglichkeit für andere Bildschirmauflösung in gui-b.mueller.cfg hinzugefügt 2025-05-20 16:49:59 +02:00
Benjamin_Mueller 05709677ac TOS-Gruppenstruktur erweitert 2025-05-20 16:39:13 +02:00
s.steuer 54606dce88 Da die Initialisierung des Netzwerkinterpreters auf U: so lange dauert wurde eine Meldung eingebaut, dass aktuell die Initialisierung erfolt, da der User ansonsten evtl. denkt, dass das Script nicht funktionier / nichts macht 2025-04-27 20:22:23 +02:00
s.steuer 2f2dd83e2b FIX - Da als Argument in '--rm_bom_ids_cfg' sowie in '--rm_summary_ids_cfg' die Umgebungsvariable $CREMIG_CFG aufgerufen wird muss cremig_setenv.bat zu diesem Zeitpunkt aufgerufen sein. Bisher wurde sie allerdings erst in manage_interpreters.bat eingelesen. Folglich wurde ein Fehler ausgegeben 2025-04-27 20:19:33 +02:00
s.steuer 0eda150f8b Debugger in allen Konfigurationen an neuen VSCode-Standard angepasst + Schalter in Konfiguration für compare_lists.py korrigiert + Syntax-Korrektur: Die vesrchiedenen Konfigurationen werden jetzt mit Kommata getrennt 2025-04-27 17:55:19 +02:00
s.steuer 58b16509da Basierend auf Commit d905896 werden nun Teilenummern, die in $CREMIG_CFG/BOM-Settings.cfg -> Sektion 'ExcludedIDsInBOM' definiert sind aus der Darstellung des Treeviews ausgeschlossen. Darüber hinaus wird nun bei Ausführung von 'Lade lokal' in der GUI die lokale Teilestamm-CSV gezogen. Bisher wurde immer vom Server generiert, was vor allem bei Tests über einen Remoteclient sehr langsam ist. 2025-04-27 17:36:41 +02:00
s.steuer 39bd9e01e2 Basierend auf Commit 21528e2 Schalter '--rm_bom_ids_cfg' und '--rm_summary_ids_cfg' ergänzt. Folglich werden bei Ausführung dieses Batch-Scripts die Teilenummern, die in $CREMIG_CFG/BOM-Settings.cfg definiert sind aus der Darstellung des Baumes, bzw. der Zusammenfassung ausgeschlossen. Darüber hinaus Präfix 'Baugruppennummer' zur Angabe der Artikelnummer, für die der Baum darstellt werden soll in 'Artikelnummer' umbenannt, da mittlerweile auch für Teilenummern ohne Stückliste der Migrationsstand angezeigt werden kann. 2025-04-27 17:32:41 +02:00
s.steuer 21528e2353 Basierend auf Commit d905896 können jetzt im Treeview Nummern aus der Stücklistenstruktur sowie aus der Zusammenfassung ausgeschlossen werden. Nummern, die explizit oder implizit ausgeschlossen wurden (implizit, wenn sie Bestandteil einer Baugruppe sind, die ausgeschlossen wurde), dann werden diese Nummern in der Zusammenfassung aufgelistet, um dem User zu verdeutlichen, dass die Darstellung des Baumes, bzw. der Zusammenfassung von der tatsächlichen Struktur abweicht. Zur Angabe der ausgeschlossenen Nummern aus dem Baum können die neuen Schalter '--rm_bom_ids_str' und '--rm_bom_ids_cfg' genutzt werden. Bei ersterem können die Nummern als Argumente nacheinander mit Leerzeichen getrennt angegeben werden. Bei zweiterem Fall wird eine Konfigurationsdatei mit darin definiertem Sektionsnamen angegeben. Analog dazu gibt es zum Ausschluss der Teilenummern aus den Anzahlen der Zusammenfassung die neuen Schalter '--rm_summary_ids_str' und '--rm_summary_ids_cfg'. Allgemein wurde auch die Angabe der Argumente konkretisiert und z.B. durch CustomActions zur Validierung der Argumente verbessert. 2025-04-27 17:29:09 +02:00
s.steuer d905896891 Klasse 'BOMConfig' sowie Methoden in Klasse 'SivasBOM' ergänzt, damit Teilenummern aus der Stücklistenstruktur herausgefiltert werden können. Aktuell ist es so festgelegt, dass wenn ein User ausgeschlossene Teilenummern an die Klasse 'SivasBOM' übergibt, diese dann auch automatisch aus der Stückliste ausgeschlossen werden, d.h. zum Ausschließen der der Nummern ist kein expliziter Aufruf der Methode '_remove_excluded_ids_from_bom' erforderlich. Hierbei gilt die Prämisse: Wenn Du ausgeschlossene Nummern angibst, möchtest Du sie auch nicht sehen. Weiso hättest Du sie sonst anggegeben? 2025-04-27 17:19:48 +02:00
s.steuer 1635610aff Config, zur Beeinflussung der Stücklisteninformationen, die defaultmäßig aus der JSON gezogen werden, ergänzt. Es wurden vorerst die Sektionen 'ExcludedPartnumbersInBOM' und 'ExcludedPartnumbersInSummary' vorgesehen. In ersterer können Teilenummern aus der Stücklistenstruktur ausgeschlossen werden. In zweiterer können Teilenummern in Zusammenfassung zur Stücklistenstruktur ausgeschlossen werden, d.h. die Nummer wird dann zwar bei einer Darstellung der Stücklistenstruktur sichtbar sein, sie wird nicht in der Zusammenfassung aufgeführt. 2025-04-27 17:11:41 +02:00
s.steuer e083f3c2ac In CreoMigrate (GUI-Applikation) können jetzt auch Sivas-Nummern, die kein Bestandteil der Menge der natürlichen Zahlen sind (z.B. 'TOS Auswahl FGN') migriert werden. 2025-04-20 18:07:07 +02:00
s.steuer 2a601ec3c1 In CreoMigrate (GUI-Applikation) können nun auch Teilenummern ohne Stückliste migriert werden. Hierfür wurde in Methode 'get_csv_files_of_asm' von 'controller.py' ein Aufruf der Methode 'extend_asm_bom' aus der Klasse 'SivasBOM' in 'manage_configs.py' ergänzt. Innerhalb der Methode wird die angegebene Teilenummer aus dem Eingabefeld in der GUI, d.h. die Hauptnummer in die Stücklistendaten aufgenommen - standardmäßig ist sie nicht enthalten. Als Oberbaugruppe dieser Nummer wird dabei die fiktive Baugruppe 'None' definiert. Durch diese Ergänzung in den Stücklistendaten wird eine Teilenummer ohne Stückliste also selbst zu einem Bestandteil der fiktiven Baugruppe 'None'. Somit wird also wie bisher nur mit Baugruppen gearbeitet, wodurch die Grundlogik zur Erstellung des Treeviews im Programm gleich bleibt. Lediglich die Vorgehensweise, wenn parent = 'None' gilt musste in den Treeview-Methoden angepasst werden. Im Zuge dessen wurde auch die Methode '_has_childs' der Treeview-Klasse in 'gui.py' angepasst, um sie effizienter zu machen. Konkret wird nun nicht mehr jedes mal durch das parent_children_mapping-dict gelooped werden, um herauszufinden, ob die angegebene Nummer enthalten ist. Da alle Nummern, die als Key in genanntem Dict vorliegen immer Kinder haben muss stattdessen nur geprüft werden, ob die Nummer als Key vorliegt. 2025-04-20 17:40:52 +02:00
s.steuer f01f08cda9 2. Backslash ergänzt, damit 1. Backslash korrekt interpretiert wird 2025-04-20 12:22:49 +02:00
s.steuer 832aaf2088 Variablennamen wurden in 'manage_configs.py' geändert (siehe commit 623f4a1) -> wurde in dieser Datei nachgezogen. Zudem in Methode 'extend_asm_bom' den Key 'Parent' mit aufgenommen, damit die Methode 'parent_children' in 'manage_configs.py' funktioniert. Dadurch kann nun auch der Migrationsstatus von Nummern ohne Stückliste im Treeview korrekt dargestellt werden. 2025-04-20 12:12:08 +02:00
s.steuer 623f4a12e1 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 2025-04-20 12:05:46 +02:00
s.steuer 56ff5010c7 In Funktion 'get_sivas_bom' wird nun in Fällen, bei denen keine JSON erzeugt werden, ein ValueError geschmissen, der ggf. später bei Bedarf per Exception gehandelt werden kann + In Funktion 'get_sivas_teilestamm' wird nun geprüft, ob das Tool 'KSbExcelExportSivasTeilestamm.exe' von Hr. Jakob mit den angegebenen Nummern tatsächlich valide CSV's generiert hat. Das ist deshalb von Bedeutung, weil das Tool auch dann CSV's erzeugt, wenn die Werte, die man per Flag '-teilenr' bereitstellt, nicht als Nummer in SIVAS vorliegen, wie z.B. 'abc' 2025-04-20 11:43:07 +02:00
s.steuer 0c54145655 In update_database.py Funktion 'get_sivas_dbase' in 'get_sivas_bom' umbenannt, da mit dieser Funktion ausschließlich die Stückliste geholt wird und somit spezifischer ist. In der Datei 'manage_configs.py' Funktionen folglich analog umbenannt. Ansonsten Funktionen in 'update_database.py' denested, um Lesbarkeit zu verbessern und Print-Statements in Deutsch geändert, da aktuell ein Mix aus Deutsch und Englisch vorliegt, was zu Verwirrung führen kann. Zudem Docstrings ergänzt und Fehler in den Print-statements behoben. Keine funktionalen Änderungen vorgenommen 2025-04-19 16:40:53 +02:00
s.steuer 3393e7ce47 Umgebungsvariable 'SIVAS_DATABASE_QUERY' in 'SIVAS_BOM' umbenannt, weil auch für die Generierung der Metadaten-CSV eine 'Database-Query' durchgeführt wird, d.h. Bezeichnung ist mehrdeutig. 'SIVAS_BOM' deshalb, weil mit dem Programm 'Sivas2Json', dessen Pfad in 'SIVAS_BOM' gespeichert ist, die Stückliste einer Baugruppe als JSON ausgegeben wird. Passt damit bezeichnungstechnisch zur Umgebungsvariable 'SIVAS_TEILESTAMM', weil mit dem Programm, dessen Pfad in genannter Umgebungsvariable gespeichert ist die Teilstamm-CSV generiert wird. 2025-04-18 23:08:22 +02:00
s.steuer 807b6c79f4 Datei redundant, da die Erstellung der Metadaten-CSV des Teilestamms bereits über die Funktion 'get_teilestamm.py' in 'update_database.py' erfolgt. 2025-04-18 22:53:45 +02:00
s.steuer 80000c15c3 Die Stücklistendaten, die aus der JSON-Datei des Programms 'Sivas2Json' erzeugt werden, wird jetzt immer die Teilenummer der Hauptbaugruppe ergänzt. Dadurch kann die Methode '_print_tree' auch die Nummer der Hauptbaugruppe schreiben. Bisher war hierfür die separate Methode '_tree_header' erforderlich. Für die Aufnahme der Hauptbaugruppe in die Stücklistendaten ist die neue Methode '_add_asm_id_to_bom' zuständig. Die Anpassung wurde vorbereitend für die nächste Erweiterung dieses Programms ergänzt, mit der es möglich sein soll, den Migrationsstand von einzelnen Teilenummern, d.h. Nummern, die keine Baugruppen sind, anzuzeigen. 2025-04-18 22:13:07 +02:00
s.steuer fe302ef950 In der Methode 'child_ids' war es unnötig für die Ermittlung aller Stücklistenpositionen das 'Parent'-Attribut der aufgelisteten Teilenummern in der JSON zu betrachten, da die Teilenummern in der JSON bereits alle Kinder der ASM darstellen / Methode 'extend_asm_bom' ergänzt, damit die Stückliste um eine Nummer ergänzt werden kann (z.B. die Nummer der Oberbaugruppe selbst, da diese aktuell in der JSON nicht ausgegeben wird). Dies wurde ergänzt, damit zukünftig auch der Migrationsstand von einzelnen Teilenummern, die keine Baugruppen sind, angezeigt werden kann, bzw. einzelne Teilenummern migriert werden können. Die entsprechende Anpassung des Treeview- bzw. GUI-Programms erfolgt in einem späteren Commit. Zudem wurde die Methode 'get_prop_val_for_single_id' ergänzt, da im Treeview-Programm bisher bei jedem Eintrag des Baums die Methode 'get_prop_val_for_all_ids' aufgerufen wurde, in der jedes Mal eine bestimmte Eigenschaft, wie z.B. 'Bezeichnung' für alle Stücklistenpositionen der Hauptbaugruppe ermittelt wurde. Das war sehr ineffizient, weil die Eigenschaft nur für den aktuellen Eintrag, d.h. die aktuelle Teilenummer, die im Baum dargestellt werden soll, benötigt wird, aber nicht für alle Stücklistenpositionen. 2025-04-18 22:03:03 +02:00
s.steuer efef193612 FIX - Die Metadaten-CSV von Teilenummern mit Leerzeichen, z.B. 'TOS Auswahl FGN' wurde bisher nicht abgeleitet. Dies funktioniert nun. Zudem Denesting durchgeführt und spezifischere Error-Checks eingebaut 2025-04-14 21:47:13 +02:00
s.steuer a1a7f45f06 pymssql in requirements aufgenommen (wird für Datenbankabfrage benötigt) und sonstige Dependencies upgedated. 2025-03-31 17:27:19 +02:00
s.steuer 9b3c3859cc get_teilestamm.py wird nicht mehr benötigt, siehe commit 4f740e81ad 2025-03-31 12:53:12 +02:00
s.steuer 22b0cf8afc In Treeview bzw. Excel-Export des Migrationsüberblicks werden Nummern nun blau markiert, wenn diese zwar in RuleDesigner migriert wurden, dort aber nocht keine Freigabe erfolgt ist. Hierfür wird der RuleDesigner-Status der Nummern live aus der RuleDesigner-Datenbank abgerufen. Dadurch ergibt sich ein detaillierterer Überblick über den aktuellen Migrationsstand, da der Großteil der Migrationsarbeit erst nach der Migration ins PDM erfolgt (Aufbereitung der Modelle, Zusammenbau der Baugruppe, etc.). Abgesehen davon wird die Bezeichnung der obersten Baugruppe jetzt ebenfalls im Migrationsüberblick angezeigt, was bisher nicht der Fall war. Hierfür wird eine CSV-Datei des SIVAS-Teilestamms zur Baugruppennummer abgeleitet daraus 'Bezeichnung 1' ausgelesen. 2025-03-29 22:19:59 +01:00
s.steuer e2bfa2aac6 FIX - An erstes Argument (BG-ID) in Methode 'get_sivas_dbase' in 'update_database.py' wurde der komplette Dateipfad zur JSON übergeben, obwohl nur die Teilenummer, bzw. max. die Teilenummer mit Dateiendung übergeben werden darf 2025-03-09 21:40:36 +01:00
s.steuer 5f3615548b Treeview angepasst, damit die Bezeichnung der obersten Baugruppe angezeigt wird, da dies bisher nicht der Fall war. Da die Bezeichnung nicht in der Baugruppen-JSON aufgeführt ist, ist es erforderlich die CSV mit den Teilestamm-Metadaten zur Baugruppennummer herunterzuladen. Damit dies möglich ist, wurde wurde in manage_configs.py eine neue Subclass 'TeilestammMetadata' ergänzt. In compare_lists.py wurden dabei weitere Flags ergänzt, mit denen gesteuert werden kann, ob die Bezeichnung aus der lokalen CSV-Datei gezogen werden sollen, oder ob die CSV mit jedem Programmlauf neu erstellt wird. Defaultmäßig wird sie mit jedem Programmlauf neu erstellt 2025-03-09 21:22:15 +01:00
s.steuer 4f740e81ad Das Einladen der JSON- und RuleDesigner-Daten erfolgt nun allein i.V.m 'manage_configs.py' und nicht mehr i.V.m der Klasse FetchSivasTeilestamm in der Datei 'get_teilestamm.py'. Dies wurde einerseits durchgeführt, um die Anzahl an Referenzen zu verringern, hauptsächlich jedoch, weil in der Klasse 'FetchSivasTeilestamm' die Klasse 'MigrationsStatus' in 'manage_configs.py' aufgerufen wird, in der wiederum Objekte der Klassen 'SivasAssemblyData' und 'RuleDesignerConfig' initiiert werden. Das ist sehr ineffizient, weil 'SivasAssemblyData' bereits in dieser Datei, also 'controller.py' initiiert wird. Es wurde zudem ergänzt, dass nun auch die lokale Version der CSV-Datei, die die RD-Teilenummern enthält geladen werden kann, ohne den aktuellen Stand vom Server zu kopieren. 2025-03-09 00:37:10 +01:00
s.steuer 6f188649ff Großes Refactoring - Dekorator für lazy-Initialisierung durch die in Python für diese Aufgabe vorgesehenen Property-Dekoratoren ersetzt. Durch diese Dekoratoren können zukünftig auch einfach Setter-Methoden ergänzt werden. Das Holen/Laden der JSON- und CSV-Dateien wurde zudem nun so umgebaut, dass dies nicht mehr in der Klasse 'MigrationsStatus' erfolgt, sondern in den Klassen 'SivasAssemblyData' und 'RuleDesignerDatabaseConfig', da dies thematisch dort auch hingehört. Die bisherige Vorgehensweise war einerseits verwirrend und zweitens ineffizient, weil in der Klasse 'MigrationsStatus' nochmal Objekte der Klassen 'SivasAssemblyData' und 'RuleDesignerDatabaseConfig' initialisiert werden mussten. Durch die Anpassung wird nun zudem die Datei 'get_teilestamm.py' nicht länger benötigt 2025-03-09 00:28:09 +01:00
s.steuer beb1fdc0da Klasse MigrationsStatus entfernt und stattdessen auf gleichnamige Klasse in manage_configs.py referenziert, um Redundanzen zu vermeiden. Zudem Flags zur Definierung des JSON-Verzeichnises, des Namens und Verzeichnisses für die CSV mit den RuleDesigner-Teilenummern ergänzt. Außerdem Flags vorgesehen, mit denen gesteuert werden kann, ob die die lokalen JSON-Dateien sowie die lokale CSV der RuleDesigner-Teilenummern verwendet werden soll. Defaultmäßig sollen bei jedem Programmlauf nun immer die neusten Daten vom Server geholt werden, bzw. immer eine JSON generiert werden, da bisher sonst nicht immer die Aktualität der dargestellten Daten sichergestellt war. 2025-03-09 00:16:27 +01:00
s.steuer da4eed34c3 Klassen 'Partnumbers', 'SivasPartnumbers' und 'RuleDesignerPartnumbers' entfernt und stattdessen mit den Klassen in manage_configs.py verknüpft, um Redundanzen zu vermeiden. Zudem doppeltes Laden der genannten Klassen in der Klasse 'RuleDesignerComparison', die jetzt 'MigrationStatus' heißt, gefixt. Abgesehen davon durch Aufrufen von Methoden in den __init__-Methoden mittels lazy-Initialisierung per property-Dekoratoren behoben. 2025-03-08 18:16:17 +01:00
s.steuer 5bd83324b2 FIX - Wenn in SIVAS keine Dispolaufgruppe angegeben ist, wird in CSV-Datei nicht ein leerer Wert, sondern ' - ' geschrieben. Bisher wurde jedoch nur bei keinem Wert eine Fehlermeldung bezüglich fehlender Dispolaufgruppe ausgegeben. Ab jetzt ist das auch beim Wert ' - ' der Fall. 2025-02-10 20:44:41 +01:00
s.steuer 1b834ab919 Wenn 'Aus Halbzeug' angehakt wird dürfen im Feld 'Farbe' keine Eintragungen vorgenommen werden. Bei Halbzeugen ist dafür das Feld 'Halbzeugfarbe vorgesehen. Konkret heißt das - sollte das Halbzeug eine Oberflächenbehandlung erhalten muss das in 'Halbzeugoberfläche' definiert werden und falls diese Oberflächenbehandlung eine Farbe erfordert dann muss diese über das Feld 'Halbzeugfarbe' spezifiziert werden. 2024-12-22 00:49:26 +01:00
s.steuer d40106d43b Materialübersetzung für 'PUR D44' ergänzt 2024-12-21 22:58:00 +01:00
s.steuer 71620fe35b Infomeldung ergänzt, wenn in CreoMigrate 'Aus Halbzeug' aktiviert wird, aber das Halbzeug noch nicht migriert wurde, oder nicht die neuste Version der RD_Teilenummern.csv im data-Verzeichnis liegt 2024-12-21 22:56:32 +01:00
s.steuer 5564befd1d Farbe 'Ocker' hinzugefügt 2024-12-21 17:17:28 +01:00
s.steuer 7f4f8e98b9 Rechtschreibfehler behoben und Text durch Bezugnahme auf SIVAS-Stückliste konkretisiert 2024-12-20 20:47:28 +01:00
s.steuer bfda1c75f6 Materialübersetzung für 'POM ' hinzugefügt. 2024-12-17 14:49:40 +01:00
s.steuer 388afbfd99 Materialübersetzung für 'S235JR+Cr' ergänzt 2024-12-16 15:18:25 +01:00
s.steuer 642d0092d1 Neu aufgenommene Werkstoffe ergänzt 2024-12-16 15:16:53 +01:00
s.steuer 55aa5f38b8 Materialübersetzung für 'POM ' hinzugefügt. 2024-12-15 20:12:28 +01:00
s.steuer dd8258f575 'filename.rsplit(.)[0] war bisher dafür zuständig, dass beim Einlesen der 'RD_Teilenummern.csv' die Endung .csv entfernt wird, um sie später beim Einlesen der Datei wieder zu ergänzen. Da die Klasse 'Partnumbers' aber auch für die json-Dateien der Teilenummern verwendet wird, hat das rsplit(.)[0] dazu geführt, dass bei Teilenummern wie z.B. 'ILS 2.0 A Pneumatik' der Teil nach dem Punkt abgecuttet wurde. Beim Versuch die json-Datei der Teilenummer zu lesen kam es dann folglich zu Fehlern, da der restliche Teil nach dem Punkt im Dateinamen fehlt und dementsprechend keine json-Datei gefunden werden konnte. Daher wird nun die Endung .csv nicht mehr abgeschnitten, sondern bis zum Einlesen in der Funktion load_from_csv() beibehalten, wobei die Dateiendung dort folglich nicht mehr als Ende hinzugefügt werden darf, da der Dateiname sonst 'RD_Teilenummern.csv.csv' lauten würde. 2024-11-22 00:37:44 +01:00
s.steuer a16f8a8845 Die Eingabeparameter 'id' in 06_migrationsstatus_treeview und -number beim Aufruf des Sivas2Json-Programms von Hr. Jakob sind nun jeweils in Anführungszeichen, damit auch Teilenummern mit Leerzeichen, wie z.B. 'TOS Auswahl ILS' korrekt verarbeitet werden können. Ansonsten endet das Parameterargument beim Leerzeichen 2024-11-22 00:25:10 +01:00
Benjamin_Mueller e2d9951e38 Materialübersetzung für 'PA 6 GF 30 Regranulat schwarz' hinzugefügt. 2024-10-28 15:41:29 +01:00
s.steuer 3704274e26 Regulären Ausdruck so angepasst, dass auch '- BG', bzw. Variationen davon aus der Bezeichnung entfernt wird. Ohne Entfernung wird beim Migrieren an das bereits bestehende '- BG' nochmal ein '- BG' angehängt 2024-10-14 15:59:55 +02:00
s.steuer dc8fb06110 FIX - Beim Einlesen der Blacklist-Nummern ist es nun egal, ob der String mit den Nummern in eine Liste geschrieben wird oder nicht. Wieso dies überhaupt passiert konnte nicht nachvollzogen werden 2024-10-14 10:52:49 +02:00
s.steuer 7492059744 Neue PP-Werkstoffe aufgenommen 2024-09-18 13:58:37 +02:00
s.steuer 0d0a9425da Default-Spritzguss-Allgemeintoleranz an cfg-Einstellungen angeglichen 2024-08-09 17:54:46 +02:00
s.steuer ccafaf6617 Besitzt die Teilenummer bei der Migration bereits einen Zeichnungsindex, aber keinen Freigabevermerk, wird nun defaultmäßig ein Minus eingetragen. Es wird immer ein Freigabevermerk benötigt, da bei Revisionen > A ohne Freigabevermerk in RuleDesigner nach den Statuswechseln 'ZUR PRÜFUNG' -> 'VERFÜBAR' -> 'IN BEARBEITUNG' -> 'VERFÜGBAR' das Revisionsmanagement erscheint, wobei beim Versuch einen Freigabevermerk einzutragen, eine Fehlermeldung erscheint. Einzige Lösung ist dann die Teilenummer aus dem System zu löschen und neu zu migrieren. Besitzt die Teilenummer hingegen einen Freigabevermerk erscheint die Fehlermeldung nach Durchführung der genannten Statuswechsel nicht. 2024-08-07 22:39:46 +02:00
s.steuer 6be81e973f Allgemeintoleranzen für Spritzgussteile angepasst, da sich die DIN ISO-Variante von der reinen ISO-Variante unterscheidet. Nur mit der DIN ISO-Variante gilt die Flächenprofiltoleranz für die gesamte Geometrie, bei der reinen ISO-Variante hingegen nicht, d.h. in diesem Fall gilt für Flächen, für die keine Flächenprofiltoleranz explizit eingetragen wurde keine Allgemeintoleranz. 2024-07-18 11:16:31 +02:00
s.steuer f070e92a0c Normen für Kanten, Oberflächen, Maße und Tolerierung werden nun mit in die Migrations-Excel geschrieben, da diese sonst in RuleDesigner und folglich bei Zeichnungsableitungen fehlen 2024-07-04 14:01:44 +02:00
s.steuer 8f82eef438 ISO 21920 aus cfg entfernt, da alle zu migrierenden Teile wenn dann immer die bisherige Oberflächennorm ISO 1302 aufweisen 2024-07-04 13:59:51 +02:00
s.steuer 9a5bae7243 FIX - Falsche Default-Allgemeintoleranz bei Fertigungsart 'schweißen' behoben 2024-07-03 16:12:11 +02:00
s.steuer b95f76341f FIX - Behoben, dass bei Kategorien != Baugruppe ein neuer Rüstcode ausgewählt werden kann, ohne dass beim Klick auf 'Migrieren' eine Fehlermeldung erscheint. Daraus resultierend musste die Übersetzung der Ruestcodes angepasst werden. Wenn nicht gewünscht ist, dass die gleichen Werte wieder in die gleichen Werte umgewandelt werden, müssen die Rüstcode-Werte in 'Allgemein.cfg' angepasst werden. 2024-07-03 15:30:49 +02:00
s.steuer 7c0ad9776c FIX - Wenn Teilenummern aus tieferen Baugruppenebenen dispoinaktiv oder beigestellt waren wurde für die aktuelle Baugruppenebene rückgemeldet, dass sie in der Blacklist fehlt. Teilenummer aus tieferen Baugruppenebenen dürfen aber nicht berücksichtigt werden. 2024-07-01 13:04:44 +02:00
s.steuer 2b0bad3cb3 Hersteller ergänzt, sodass Liste mit Werten in RuleDesigner übereinstimmt 2024-07-01 12:11:37 +02:00
s.steuer 61999ea966 Automatische Zusatzinformationen für die Fälle ergänzt, wenn sich dispoinaktive Positionen in der Stückliste befinden, da in diesen Fällen keine Stückliste übergeben werden darf (BG-Nummer muss sich in Blacklist befinden) 2024-06-17 17:27:43 +02:00
s.steuer b814ffa70d Weitere Werkstoffübersetzungen ergänzt 2024-06-17 17:26:02 +02:00
Benjamin_Mueller 68266a3345 Werkstoff 1.0242+Z275 MAC (S250 GD+Z275 MAC) hinzugefügt 2024-06-17 14:32:49 +02:00
s.steuer 44a116fb6e FIX - Im Feld 'Bezeichnung 1' der Spalte 'Überschriebene Werte' in CreoMigrate soll nur dann ein Wert dargestellt werden, wenn 'KPL.' (oder eine Abwandlung davon) aus der Bezeichnung entfernt wurde. Bei unveränderter Bezeichnung (z.B. bei Einzelteilen) soll das Feld hingegen leer bleiben. 2024-06-16 22:53:48 +02:00
s.steuer 7a6b331e27 FIX - Wenn die Spalte 'HalbzeugExtern' in SIVAS-CSV befüllt war, wurde dessen Inhalt in CreoMigrate in das Feld 'Halbzeug' in der Spalte 'SIVAS-Werte geschrieben, da das Mapping der CSV-Werte falsch war. 2024-06-16 22:32:17 +02:00
s.steuer 09b8ee7e6e Vor Durchführung der Migration wird nun zusätzlich geprüft, ob Teilenummern in der Blacklist fehlen. Ist immer dann der Fall, wenn eine Teilenummer eine Stückliste besitzt und sich darin Positionsnummern befinden, die beigestellt oder dispo-inaktiv sind. 2024-06-16 21:59:47 +02:00
s.steuer c070f1fd28 Neuen Werkstoff 'siehe Stückliste' aufgenommen 2024-06-14 16:19:22 +02:00
s.steuer 66260e23ef Eingebaut, dass neuster Stand der Blacklist bei jeder Suche kopiert wird, da sich häufig Änderungen darin ergeben. 2024-06-13 09:56:11 +02:00
s.steuer cd5feb94c8 FIX - Oberflächenbehandlung konnte bei Schweißbaugruppen nicht ausgewählt werden, da Feld in diesem Fall bisher disabled war + In 'Automatische Zusatzinformationen' neue Variante aufgenommen, wenn das Halbzeug bei einer Halbzeugbearbeitung dem Lieferanten beigestellt wird, also in der Blacklist vorliegt 2024-06-11 13:11:04 +02:00
s.steuer e73fea929d FIX - Logik für Felder 'Mengeneinheit' und 'Halbzeug' berichtigt 2024-06-06 11:35:26 +02:00
s.steuer 7dee350422 States bei verschiedenen Feldern überarbeitet, damit Felder nicht ausgewählt werden können, wenn dies keinen Sinn ergibt + teilweise Rechtschreibfehler und fehlerhafte state-Bezeichnungen korrigiert 2024-06-06 10:37:09 +02:00
Benjamin_Mueller c50d0b937c Automatische Materialübersetzung für 1.4310 hinzugefügt 2024-06-06 10:06:15 +02:00
s.steuer ef80d62f0c FIX - Aufgrund von Leerzeichen im Werkstoff konnte RDX-Altdatenmigrations-Prozess keinen Werkstoff zuweisen, sodass Teil nicht migriert werden konnte. 2024-05-27 17:09:15 +02:00
s.steuer ab24f24bba FIX - Bei Schweißbaugruppen konnte die FOS-Gruppe nicht geändert werden. Diese wird nun automatisch korrekt eingetragen. Zudem war bei Schweißbaugruppen als FOS-Gruppe bisher '1 - Baugruppe' vorgesehen. Richtig ist aber '0 - Einzelteil' 2024-05-27 15:01:46 +02:00
s.steuer 4356ed2cc1 FIX - Bei PDM-Kategorie 'Schweissbaugruppe' konnten keine Oberflächenbehandlungen ausgewählt werden, obwohl dies unter Umständen erforderlich ist. Wurde behoben. In 'cfg/Oberflächenbehandlung.cfg' wurde für die Schweissbaugruppen-Oberflächenbehandlungen eine eigene Sektion ergänzt 2024-05-24 14:45:16 +02:00
Benjamin_Mueller e500b20fc5 Weitere Materialübersetzung für 1.0038 hinzugefügt 2024-05-16 17:14:52 +02:00
s.steuer 15e4f01f83 Für die Allgemeintoleranzen von Biegeteilen wurde in RuleDesigner ein neues getrenntes Feld 'AllgemeintoleranzBiegen' erstellt, da beim Biegen gesonderte Allgemeintoleranzen (z.B. bei Federn) auftreten, die nicht für anderen Verfahren gelten. Das bisherige RuleDesigner Feld 'AllgemeintoleranzSpanen' konnte also nicht weiter für Biegeteile verwendet werden. Diese Strukturänderung wurde in das Programm übernommen. 2024-05-15 14:39:02 +02:00
s.steuer e20a34d254 FIX - Bezeichnung des RAL-Code muss jeweils im Farbnamen enthalten sein. Andernfalls kommt es zu ERP-Schnittstellenfehlern 2024-05-07 14:35:13 +02:00
s.steuer da29b7b33e FIX - Oberfläche wurde nicht übersetzt, obwohl sie in 'Materialübersetzung.json' in den jeweiligen json-Objekten enthalten war. Grund: Es wurde überprüft, ob der Name des bereits übersetzten Materials in der 'Materialübersetzung.json' vorhanden ist. Es muss aber geprüft werden, ob der Materialname aus Sivas als Objekt in der 'Materialübersetzung.json' vorhanden ist. 2024-05-07 14:32:01 +02:00
Benjamin_Mueller a5837526be Weitere automatische Materialübersetzung hinzugefügt 2024-05-07 13:01:42 +02:00
s.steuer f8360c1af0 FIX - Keine Rüstcode aus SIVAS wurde nicht in neuen Rüstcode 'Trümmerbaugruppe' umgewandelt. Dies lag daran, dass Spalten ohne Wert in der CSV-Datei als 'None' interpretiert werden. Bei der Umwandlung der Rüstcodes wurde aber nicht geprüft, ob der Wert 'None', sondern ein leerer String ist. 2024-05-07 12:49:36 +02:00
s.steuer 5d3a8e5237 Merge branch 'main' of http://gitea.schoenenberger.de/mistangl/CreoMigrate 2024-05-06 10:48:42 +02:00
s.steuer ecd2ac37d7 FIX - Bei der Feldüberprüfung, ob sich unzulässige Zeichen im Feld befinden, darf das Material aus SIVAS (in GUI-Spalte 'SIVAS-Werte' nicht überprüft werden. Bisher wurde dieses Feld berücksichtigt. 2024-05-06 10:48:28 +02:00
Benjamin_Mueller 24ac020314 Egränzung der Materialübersetzungsdatei 2024-05-06 10:34:54 +02:00
s.steuer 94f2aeb027 Fehlende Farbe 'siehe Oben' ergänzt 2024-05-02 17:07:36 +02:00
s.steuer 1f52aa697b Weitere Materialübersetzungen ergänzt 2024-05-01 16:45:42 +02:00
s.steuer e0c5b87c08 FIX - Rechtschreibfehler behoben 2024-04-29 16:18:37 +02:00
Benjamin_Mueller b01e778216 Materialübersetzung für POM Weiß hinzugefügt 2024-04-26 11:04:50 +02:00
Benjamin_Mueller 3976d66ccf Weitere automatische Materialübersetzung für POM schwarz hinzugefügt 2024-04-18 10:13:38 +02:00
m.stangl c8e958ef32 Länge der Bezeichnung wird beim Migrieren Knopf überprüft. Bei Baugruppen und Schw.Bgrp ist nach 45 Zeichen schluss, beim Rest nach 50 Zeichen 2024-04-17 14:50:13 +02:00
Benjamin_Mueller b7585c1975 Felder von Bezeichnung 1 verbreitert um Eintrag besser lesen zu können / automatischer Längenbeschnitt der Bezeichnung 1 neu entfernt 2024-04-17 09:27:08 +02:00
Benjamin_Mueller 32fb4999cc Entfernung der Breitenbeschränkung der Felder Baugruppennummer & Teilenummer. 2024-04-15 15:13:33 +02:00
Benjamin_Mueller 023929fce2 Vorbelegung des Defaultwertes der Allgemeintoleranz in der Kategorie Baugruppe von '' auf 'ISO 2768:1991-mK' abgeändert 2024-04-15 14:50:05 +02:00
s.steuer 89a4f1bfe0 FIX - Beim Schreiben des Spaltenwertes 'HalbzeugeOhneSaegeliste' wurde geprüft, ob eine Halbzeuglänge vorliegt. Es muss aber korrekterweise geprüft werden, ob ein wert in 'Halbzeug ohne Sägeliste' vorliegt. 2024-04-10 15:36:44 +02:00
Benjamin_Mueller ba3cc9c6fa Trümmerbaugruppe zu Translationsliste hinzugefügt. Eine Doppeltbeschreibung eines Defaultwertes entfernt 2024-04-10 12:08:54 +02:00
Benjamin_Mueller 5058457714 Erweiterung der automatischen Materialübersetzung, POM schw wurde aufgenommen 2024-04-10 09:06:11 +02:00
Benjamin_Mueller 07a22c5c11 Userspezifische GUI-Configs nun möglich 2024-04-09 13:29:41 +02:00
Benjamin_Mueller bc06323061 Merge branch 'main' of http://gitea.schoenenberger.de/mistangl/CreoMigrate 2024-04-09 12:44:48 +02:00
Benjamin_Mueller dcb8830d8c Steuerung der Oberfläche über eine cfg-Datei 2024-04-09 12:44:40 +02:00
s.steuer 77584c8749 Merge branch 'main' of http://gitea.schoenenberger.de/mistangl/CreoMigrate
Allgemeintoleranz wird nun eingetragen, wenn in SIVAS ein
Fertigungsverfahren vorliegt.
2024-04-09 12:34:17 +02:00
s.steuer c1f860d3c5 Wenn ein Einzelteil migriert wird, für das in SIVAS bereits ein Fertigungsverfahren festgelegt wurde, wurde keine Allgemeintoleranz vorausgewählt. Sie konnte dann nur festgelegt werden, indem das Fertigungsverfahren erneut in der Spalte 'Überschriebene Werte' gewählt wurde. Nun wird die Allgemeintoleranz automatisch abhängig vom Fertigungsverfahren in die Spalte 'SIVAS-Werte' eingetragen. 2024-04-09 12:34:13 +02:00
Benjamin_Mueller dde4ee997e Schalter -w eingebaut, um zu steuern, ob die CSV-Dateien erneut heruntergeladen werden sollen. Erforderlich, weil bisher bei Klick auf 'Suche' in GUI die CSV nicht erneut heruntergeladen wurde, obwohl in Sivas Änderungen durchgeführt wurden, d.h. die aktualisierten CSVs benötigt werden. 2024-04-09 11:18:50 +02:00
Benjamin_Mueller 6a671b7c6f LW, Laser und Wasserstrahl war in der config anders geschrieben als im Code. Mausrad steuert jetzt nicht mehr das komplette Canvas, so dass man mit der Scrollbar den Ausschnitt verändern muss. Combo der Fertigungsart enthält jetzt einen leeren Eintrag, damit man nach zufälliger Auswahl diese auch wieder herausnehmen kann 2024-04-09 09:53:23 +02:00
Benjamin_Mueller 884750a2ae FIX Automatische Leerung des Parameters 'Bezeichnung1_neu' eliminiert. Parameter funktioniert nun wie gewünscht. 2024-04-09 09:22:29 +02:00
Benjamin_Mueller 83cea43c9c Zusätzliches Aluminium sowohl in Auswahlliste, als auch in Übersetzungsliste aufgenommen 2024-04-08 09:41:36 +02:00
s.steuer 37c791e6c5 FIX - wenn Haken in 'Aus Halbzeug' nicht gesetzt war wurde kein Wert in Excel-Spalte 'HalbzeugInternAngabe' zurückgegeben. Es wird in diesem Fall aber 'Nein' benötigt. Dies wurde behoben 2024-04-04 13:52:01 +02:00
s.steuer 660f27936d Aufruf von 'cb_3Dmodel_neu' eingebaut, wenn 'Aus Halbzeug' gewählt wird, damit auf leeres 3D-Modell im Pfad verwiesen wird, sobald 'Aus Halbzeug' angehakt wird (gemäß Spezifikation) 2024-04-04 11:11:09 +02:00
s.steuer 11f57055f2 FIX - Wenn 'Aus Halbzeug' aktiviert ist wurden 'cb_material_neu' und 'cb_oberflaeche_neu' nicht aufgerufen. Dadurch konnte weiterhin ein Werkstoff und eine Oberfläche ausgewählt werden, was nicht passieren darf. 2024-04-04 10:55:48 +02:00
s.steuer 479519285c Vor dem Verschieben der Log-Datei wird nun geprüft, ob die Log-Datei noch existiert, da andernfalls eine FileNotFound-Exception ausgegeben wurde, wenn die Ausführung des DataPrepTools fehlerfrei funktioniert hat. In diesem Fall wurde die Log-Datei bisher gelöscht, existierte folglich also nicht mehr, sobald shutil.move ausgeführt wurde 2024-04-04 10:34:43 +02:00
s.steuer 14654ac367 Merge branch 'main' of http://gitea.schoenenberger.de/mistangl/CreoMigrate
FIX für Zeilenumbrüche in Spalten 'Freigabevermerk',
'Änderungsbeschreibung' und 'Zusatzinformationen' + Eingebaut, dass
Werkstoff bei Teilen, die aus Halbzeug gefertigt werden, nicht in Excel
geschrieben wird
2024-04-04 10:04:34 +02:00
s.steuer 3473b2c37c Feld 'Zusatzinformationen' aus Feldprüfung entfernt, da dieses Feld je nach Fall auch leer sein darf + Werkstoff wird nun bei Einzelteilen, die aus einem Halbzeug gefertigt werden, nicht mehr in die Excel geschrieben, da der Werkstoff in diesem Fall durch das Halbzeug definiert wird. 2024-04-04 10:04:13 +02:00
s.steuer 339ba53257 Zeilenumbrüche in den Feldern Änderungsbeschreibung, Freigabevermerk und Zusatzinformationen werden nun entfernt, da dies zu Problemen bei der Übergabe an SIVAS führt 2024-04-04 10:01:37 +02:00
m.stangl 5b6f32f404 Merge branch 'main' of http://gitea.schoenenberger.de/mistangl/CreoMigrate 2024-04-03 17:19:56 +02:00
m.stangl c06837948f FIX zur Bestimmung der Halbzeuglänge aus der assembly.json Datei und dem zugehörigen Längeneintrag dieses Teils 2024-04-03 17:19:48 +02:00
s.steuer 84626705e8 FIX für Spaltennamen implementiert 2024-04-03 14:12:37 +02:00
s.steuer 3a2d7c075d FIX für 'Halbzeug ohne Sägeliste', 'KategorieNE' & 'RüstcodeAusw' implementiert 2024-04-03 14:05:09 +02:00
Benjamin_Mueller 17a4d4e38a FIX verschiebung der Logdatei in korrektes Verzeichnis jetzt möglich 2024-04-03 13:26:27 +02:00
m.stangl b48060aabc notepad zum Betrachten der logs als Default dazu. 2024-04-03 13:07:00 +02:00
m.stangl aeb35b4d43 Fix beim Migrieren. Logs werden in Log Ordner geschoben. Notpad geht im Fehlerfall auf 2024-04-03 12:12:02 +02:00
Benjamin_Mueller 1d23117f2f Defaultvorbelegung von Halbzeugoberfläche & Farbe verändert, FIX zusätzlicher cb der Halbzeugoberfläche 2024-04-03 11:23:44 +02:00
Benjamin_Mueller 5c92c3eaec Behebung von 2 Bugs, erneuter Pfadabgleich nach Auswahl 'Neuaufbau' & Halbzeugnummerabfrage nach Auswahl 'aus Halbzeug' 2024-04-03 11:13:13 +02:00
m.stangl a4f07d3e33 Impfen mit dem DataPrep Werkzeug eingebaut 2024-03-28 16:26:36 +01:00
Benjamin_Mueller b5b0c58f39 In Fertigungsarten Sektion Verpressen hinzugefügt. FIX der Zusammensetzung des New Filenames, Punkt hatte gefehlt. Korrektur der Reihenfolge der Excelspalten 2024-03-26 17:10:55 +01:00
m.stangl 9c87541a49 FIX: Pandas File mit Header und ohne Index schreiben 2024-03-26 13:37:45 +01:00
m.stangl c8ee75f80c Fix: Pfade werden auch ausgeben. Fix: Laser und Wasserstrahlschneiden war im Code anders geschrieben als in der config 2024-03-26 11:50:27 +01:00
m.stangl ef8686d714 Merge branch 'main' of http://gitea.schoenenberger.de/mistangl/CreoMigrate 2024-03-26 10:57:12 +01:00
m.stangl cf79b32fc2 Pfade in die create_migration_data funktion verschoben 2024-03-26 10:57:03 +01:00
Benjamin_Mueller de3899accf Merge branch 'main' of http://gitea.schoenenberger.de/mistangl/CreoMigrate 2024-03-26 10:30:14 +01:00
Benjamin_Mueller 7b7df71279 Anpassung der Reihenfolge der Excelspalten in caditem.py, an bisherige Excel angeglichen. Kommentare ergänzt welche Spalten noch fehlen und wo sie zu platzieren sind. 2024-03-26 10:29:43 +01:00
s.steuer 3ba2a6ccdc Automatische Zusatzinformation bezüglich Kleinbuchstaben-Indizes präzisiert sowie ergänzt, dass Kleinbuchstabenindex nach Freigabe des Datensatzes in RuleDesigner wieder in SIVAS freigegeben werden muss 2024-03-23 23:34:41 +01:00
m.stangl 9747f7996c Merge branch 'main' of http://gitea.schoenenberger.de/mistangl/CreoMigrate 2024-03-22 11:35:40 +01:00
m.stangl dd1362fec8 Fix: 'Version' wurde in der csv Dateie als Zahl erkannt und sollte beim Einlesen als String gelesen werden. 2024-03-22 11:35:34 +01:00
s.steuer 780974081b Fehlermeldung eingefügt, wenn Blacklist nicht in lokalem Verzeichnis liegt + Bei Feldüberprüfung des Feldes 'Halbzeugfarbe' wurde bisher geprüft, ob sich im Feld 'Oberfläche' ein Wert befindet. Eigentlich soll aber geprüft werden, ob sich ein Wert im Feld 'Halbzeugoberfläche' befindet. Dies wurde ebenfalls gefixt 2024-03-21 13:16:41 +01:00
m.stangl 8511f224f6 Oberfläche anpassbar an querstehende Bildschirme 2024-03-21 10:52:13 +01:00
m.stangl 8e6b7466a6 Export der Migrationsfunktion bestückt. 2024-03-19 17:05:48 +01:00
Benjamin_Mueller 0e4b218563 um Exportfehlermeldungen ergänzt beim Migrieren 2024-03-19 15:54:19 +01:00
Benjamin_Mueller ba11ad68ea POM in Config aufgenommen 2024-03-19 15:13:58 +01:00
Benjamin_Mueller 1c18ca98bf gui.bat lädt jetzt die virtuelle Umgebung. Fix der Abfrage eines Bauteils als Assembly implementiert. Kein Exit im Code mehr, der als Library verwendet werden soll. 2024-03-19 14:02:54 +01:00
Benjamin_Mueller 13faea2164 Division durch 0 verhindern 2024-03-19 13:23:45 +01:00
m.stangl 83a250e66b Statistik in den tree eingebaut. Ein paar Fixes in der Logik. Erweiterungen des 2024-03-19 13:17:31 +01:00
m.stangl 6d52f160e8 Highlight der labels implementiert. 2024-03-18 16:31:20 +01:00
m.stangl 198a9a1d62 Baum Zeigt manipulierte Daten in orange an. nicht benutzte Methoden von caditem auskommentiert. 0
Delete
Document Number	-
Revision	-
Project Name	-
Teamcenter Item Type	-
Part Type	-
TC_ImportTime	-
Last Saved Version	-
Subject	-
Category	-
Keywords	-
Teilenummer	400102274
Title	Gefällebogen 30° beschnitten
Bezeichnung4
Author	m.stangl
StartRevision	A
Aus Halbzeug
Fertigungsart	Einzelteil
Mengeneinheit	Stck
Halbzeug
TOS-Gruppe	Schönenberger Produkt
TOS_Schoenenberger_Produkt	ILS IntraLogistikSystem
TOS_ILS	ILS 2.0
TOS_ILS_2	Gefälle
Dispogruppe	Förderer
Dispolaufgruppe	Intra Logistic System + alt-HFS
ZusaetzlicheInformationen
	0
Delete
Document Number	-
Revision	-
Project Name	-
Teamcenter Item Type	-
Part Type	-
TC_ImportTime	-
Last Saved Version	-
Subject	-
Category	-
Keywords	-
Teilenummer	400102274
Title	Gefällebogen 30° beschnitten
Bezeichnung4
Author	m.stangl
StartRevision	A
Aus Halbzeug
Fertigungsart	Einzelteil
Mengeneinheit	Stck
Halbzeug
TOS-Gruppe	Schönenberger Produkt
TOS_Schoenenberger_Produkt	ILS IntraLogistikSystem
TOS_ILS	ILS 2.0
TOS_ILS_2	Gefälle
Dispogruppe	Förderer
Dispolaufgruppe	Intra Logistic System + alt-HFS
ZusaetzlicheInformationen
  Export
2024-03-18 13:50:40 +01:00
m.stangl 1eb42b2366 Demodaten rausgeworfen. Nicht mehr nötig da mit Echtdaten anwendbar. Prüfung aller Eingaben beim Migrieren aktiviert. 2024-03-18 11:04:38 +01:00
m.stangl e3a7e79dad Generierung der Export Daten. TOS Gruppenfolge aus der TOS Nummer impl. 2024-03-15 14:07:59 +01:00
m.stangl a785eecbc2 Alle Check Logiken Implementiert 2024-03-14 14:24:37 +01:00
m.stangl 8ec356df70 Content Check weiter getrieben bis zur Kalkulationsart 2024-03-13 12:40:31 +01:00
m.stangl 8f74aac945 Test auf invalid Characters implementiert. ERP_Item.ini rausgeschmissen. Sonderzeichen im Configparser nicht einfach zu lesen. FileEncoding war auch nicht utf-8. Eigene Textdatei für Sonderzeichen 2024-03-13 11:44:12 +01:00
m.stangl 1e917e5bbd Check der Inhalte mit beider Spalten mit nur einem Rückgabewert versehen. Ansonsten unverständliche für den Nutzer. 3D Druck Keyword im Ruledesigner unterschiedlich. Beide Varianten erlaubt. Rückgabe von keiner Fertigungsart führt zu keinen Defaultwert der folgenden Comboboxen. Keine Exception deswegen mehr 2024-03-12 17:28:58 +01:00
m.stangl b6f9f1a4bf Config Einträge korrigiert und ERP_Item.ini für die unzulässigen Zeichen mit eingecheckt. 2024-03-12 17:26:17 +01:00
m.stangl 3fc8c495f0 Werkstoffdiskrepanz Key umbenannt 2024-03-12 15:35:40 +01:00
m.stangl dd20c42851 Logik für Freigabevermerk und ZUsatzinfos implementiert 2024-03-12 14:57:47 +01:00
m.stangl 997592e17f alle Pflichtfdler labels blau gemacht. Clear der gui vor jedem Laden der Modellinfos eingefügt. ruestcode_sivas 2024-03-12 14:57:17 +01:00
m.stangl 1b6d3feaa4 blacklist auslesen impl. 2024-03-12 14:54:24 +01:00
m.stangl f471138b96 clear funktionen für die gesamte Oberfläche implementiert. Zuruecksetzen Knopf implementiert. Combo Felder immer readonly gesetzt 2024-03-11 17:42:59 +01:00
m.stangl f0370fa5cd Merge branch 'main' of http://gitea.schoenenberger.de/mistangl/CreoMigrate 2024-03-11 16:09:07 +01:00
m.stangl f7dd9d49f3 'Herstellerteilenummer' als Callbackfunktion nur für Statusübergang impl.; version_neu rausgeschmissen nach neuer Spec; restliche Statusübergänge impl. 2024-03-11 16:09:00 +01:00
s.steuer bfef814673 Aus Spalte 'Überschriebene Werte' wurde das Entry-Feld 'Version' in Folge der Berichtigung des Spezifikationsduments entfernt, da dieses Feld nur informativ den Wert aus SIVAS darstellen soll, aber unter keinen Umständen eine Überschreibung erforderlich ist, zumal dieses Feld auch nicht in der Impfdatei berücksichtigt wird 2024-03-08 22:24:35 +01:00
s.steuer aae5196bc1 Sektionsnamen, die bisher 'Version' enthielten in 'Kleinbuchstabe' umbenannt, da eindeutiger und verständlicher 2024-03-08 22:22:06 +01:00
s.steuer 6217a41bd9 Spezifikationsfehler in den Feldern Version und Änderungsindex korrigiert + kleinere sonstige Spezifikationsfehler behoben + Markdown-Links zu Abschnitten berichtigt + Beispielbild für Fehlermeldung bei Überschreitung der Zeichengrenze beim Änderungstext geändert sowie Bild für Fehler bei Überschreitung der Zeichengrenze beim Freigabevermerk hinzugefügt 2024-03-08 22:20:25 +01:00
m.stangl c470729918 set_states methoden für alles in der gui implementiert. Bugfix im Tree: Zuordnung tree-Id und Sivas-Id in einem dict merken, um den Doppelklick verarbeiten zu können 2024-03-08 18:44:24 +01:00
m.stangl 05392ef5e9 Fix des Baumviews. ChildIds wurden nicht aus dem Pool genommen 2024-03-07 23:56:33 +01:00
m.stangl db6b3b7329 Merge branch 'main' of http://gitea.schoenenberger.de/mistangl/CreoMigrate 2024-03-07 17:16:15 +01:00
m.stangl 1b8270b908 Statusänderungen der Knöpfe begonnen. Treeview ist noch nicht korrekt. 2024-03-07 17:16:08 +01:00
m.stangl 94ff9aa100 erstes Grundgerüst in mvc gebaut, um den Status einzusammeln und an die gui weiter zu geben 2024-03-07 12:32:04 +01:00
m.stangl 3dc8af5e70 diverse Ergänzungen in den Abhängikeiten der Callbackfunktionen. Strings der Fertigungsarten haben Kürzel. Callback der fos Gruppe geändert 2024-03-06 17:13:15 +01:00
m.stangl 2e3061d238 migration impl. Erst Abgleicher Oberfläche und des Modells vor speichern oder migrieren 2024-03-06 17:11:24 +01:00
m.stangl 9fec1a91f4 Umbau der gui: Überschriften weiter unten. Texte werden auf länge geprüft, bevor sie ins Widget kommen. Umbau des Radiobuttons mit einer StrVariable 2024-03-06 17:10:31 +01:00
m.stangl 6a569c685a Allgemeintoleranz Spanen war noch nicht in der Config 2024-03-06 17:08:49 +01:00
Benjamin_Mueller 1f05543524 In TOS-Gruppen.json die Struktur für TOS-Gruppen 4390 / 4391 / 4392 hinzugefügt 2024-03-06 08:21:16 +01:00
m.stangl 00f180ea39 Verweise für die Pflichtfelder aus der spec rein kopiert. 2024-03-05 17:45:00 +01:00
m.stangl fddcbb058e einige Bugs gefixt. Weiter Abhängigkeiten eingepflegt 2024-03-05 16:25:20 +01:00
m.stangl b52e36fe57 Textfelder anstatt entries verwendet. Breite und Höhe der Felder in der Zentralen Klasse änderbar 2024-03-05 14:32:26 +01:00
m.stangl 2945be89d3 an Logik weiter gebaut. Material und Werkstoff rein 2024-03-04 17:49:38 +01:00
m.stangl 85fec18c4a Doppelpunkt ':' als delimiter in der Config deaktiviert 2024-03-04 17:49:11 +01:00
m.stangl 841b8745b6 Merge branch 'main' of http://gitea.schoenenberger.de/mistangl/CreoMigrate 2024-02-29 19:05:23 +01:00
m.stangl 46d3bbd77b Logik weiter getrieben. Debug von cb_halbzeugOhneSaege 2024-02-29 19:05:15 +01:00
m.stangl 466ae4afd5 Methode zur Ausgabe aller Werkstoffe in der Werkstoff.cfg 2024-02-29 19:04:44 +01:00
Benjamin_Mueller aabf626b78 Korrektur eines Parameternamens in der Datei TOS-Gruppen.json 2024-02-29 15:52:01 +01:00
m.stangl 95e4c366d6 weiter die Logiken einprogrammiert 2024-02-29 14:49:28 +01:00
m.stangl 4d42f82e6a Messages info bzw. error hinzu 2024-02-29 14:49:09 +01:00
m.stangl 650b07687b Default Wert nach oben geschoben 2024-02-29 14:48:22 +01:00
Benjamin_Mueller 397457b20e Der Datei TOS-Gruppen.json wurden in jedem TOS-Gruppenlevel, ausser dem obersten, Kommentare eingefügt wo das Objekt im Strukturbaum in SIVAS zu finden ist. 2024-02-29 10:35:34 +01:00
Benjamin_Mueller b13800b797 Mitteilungstext in der Datei write_tos_string_to_file.bat korrigiert 2024-02-29 09:13:58 +01:00
Benjamin_Mueller ebaedd574b Erweiterung der TOS-Gruppen.json Datei um zusätzliche TOS-Gruppen 2024-02-29 09:01:27 +01:00
Benjamin_Mueller 5327789473 Bat-Datei zum direkten Herausschreiben des TOS-Strings in eine Datei ohne CMD 2024-02-28 16:00:18 +01:00
m.stangl fc1b1bc946 data_from_view impl. um ein anderes Assembly zu laden. Weiteren Konpf 'lade lokal' gebaut, um Daten auch ohne weitere Serverabfrage zu laden welche lokal existieren. 2024-02-21 14:46:53 +01:00
m.stangl 5e65dc2b36 Default methoden für alle callbackroutinen rein. Umbau des Aufrufs der gui, um auch assemblies laden zu könenn 2024-02-20 12:51:38 +01:00
m.stangl 74df118118 codeblock war nicht richtig dargestellt 2024-02-20 09:41:39 +01:00
m.stangl f16902fd01 Logik zu Rüstcode rein 2024-02-19 14:55:22 +01:00
m.stangl 39e5f3ddbb Logik weiter gebaut bis Bezeichnung 1. Überprüfungen der Bezeichner nach kpl./KPL. Abhängigkeiten davor wie Farbe, Oberfläche usw. ergänzt 2024-02-15 18:57:05 +01:00
m.stangl f7033ebe76 kleinere Umbauarbeiten am Hauptframe. Callbackfunktion für ein Entry gebaut, das Längenabhängig den Text einfärbt 2024-02-15 18:55:39 +01:00
m.stangl 4fe5c37bb5 Statusänderungen wie readonly, etc im Controller bzw. der gui vorgesehen 2024-02-15 18:54:41 +01:00
m.stangl 3e97c2aeec data Verzeichnis auch an Config objekt übergeben 2024-02-15 18:53:18 +01:00
m.stangl f21e218420 data/RD_Teilenummern.csv auch mit im Config Objekt verwalten 2024-02-15 18:52:25 +01:00
m.stangl e63e127bef einige Attribute protected gemacht 2024-02-15 11:09:32 +01:00
m.stangl 2dc83248ee Logik zur Selektion des Pfades des 3d Bauteile geändert 2024-02-14 19:05:39 +01:00
m.stangl 8c109eebcd Config Zielpfade.cfg mit TEstblock versehen 2024-02-14 19:04:54 +01:00
m.stangl 9f1402bc55 fix in der Controllerlogik, wann der Suche Knopf gedrückt werden kann 2024-02-14 19:04:02 +01:00
m.stangl b0b65f0614 gui um Selectionsbox für Pfad zu 3D Modell ergänzt. callbacks der Knöpfe erfolgt jetzt nur noch im Controller. 3D-Modell Pflichtfeld implementiert 2024-02-14 16:07:29 +01:00
m.stangl 5f781c513b get_sivas_dbase mit docstring versehen 2024-02-14 16:06:12 +01:00
m.stangl a0be038bbf Aufruf mit -use_local möglich, so dass auch das kopieren vom Netzlaufwerk nicht stattfindet. 2024-02-14 16:05:42 +01:00
m.stangl 76fde13623 get Funktion für IniConfigParser dazu 2024-02-14 16:04:47 +01:00
m.stangl e4c7ccf152 ein paar Variablen in caditem protected gemacht. Laden und Speichern der ausgefüllten Oberfläche im json file im Work Ordner implementiert 2024-02-14 10:43:33 +01:00
m.stangl 501c862eeb Bedingungen für aus_halbzeug impl. 2024-02-14 09:21:32 +01:00
m.stangl b128cfb5e6 Checkboxen auch als tk.Boolean definiert. Ansonsten gehen die Callbacks nicht 2024-02-13 09:24:23 +01:00
m.stangl b527faf086 Schalter -use_local dazu. Keine Datenbankabfrage vom Server, wenn die Dateien schon da sind. EInige Attribute im config manager privatisiert. In die Logik auch die Abhängigkeit der comboboxen definiert. Controller ist jetzt ein Observer (der einzige) 2024-02-12 17:19:42 +01:00
m.stangl 8c6d91b463 Observer pattern eingebaut. Zahlreiche Attribute protected gemacht. Logik in caditem verschoben. config aus der gui entfernt 2024-02-08 18:36:57 +01:00
m.stangl e082dec1e1 create_gui_dependencies mit eval implementiert. Spart Schreibarbeit und ermöglicht es Callbackfunktionen über Einfache Aufrufe mit den Namen der Callbackfunktionen zu tätigen 2024-02-08 16:02:25 +01:00
m.stangl bd4b8d297e gui Aufruf mit einem Assembly holt sich alle nötigen Infos von den DAtenbanken. 2024-02-07 10:41:23 +01:00
m.stangl 4777f5afbf Aufruf der Methoden aus manage_configs zur Erzeugung aller nötigen .csv Dateien und der .json Datei der Baugruppe 2024-02-07 10:39:21 +01:00
s.steuer f6e955601d Falsche Parameterreihenfolge korrigiert 2024-02-06 15:34:43 +01:00
s.steuer 896cf7a227 Musste angepasst werden, da Funktion aus get_sivas_teilestamm.py in update_database.py umgezogen wurde 2024-02-06 15:00:53 +01:00
s.steuer 2e76c4d959 Library ergänzt, um die Teilestamminformationen von allen nicht migrierten Teilenummern einer Baugruppe als CSV ableiten zu können 2024-02-06 14:59:31 +01:00
s.steuer e87c1b930c Extrahierung der migrierten oder nicht migrierten Teilenummern der Baugruppenstückliste eingebaut 2024-02-06 14:57:57 +01:00
s.steuer 920c7bf0f3 Merge branch 'main' of http://gitea.schoenenberger.de/mistangl/CreoMigrate 2024-02-06 14:51:41 +01:00
s.steuer 740a1b2ac8 CSV-Teilestammableitung aus get_sivas_teilestamm.py in update_database.py umgezogen 2024-02-06 14:45:33 +01:00
m.stangl 6f2402dea4 Comboboxen nicht mehr befüllen, da sie nach dem Start ja auch leer sein müssen. 2024-02-06 12:38:10 +01:00
m.stangl 716ff80905 Callbackfunktionen gleich benannt wie die jeweiligen Callbacks. Pflege der DAten beim csv Import immer gleich nach dem Aufruf der Callbackfunktion, da jede Callback auf Daten daraus zugreift 2024-02-06 12:37:28 +01:00
m.stangl 6c1bb728c7 fix:Halbzeugfarbe Callback vergessen 2024-02-06 12:34:52 +01:00
m.stangl 8e6b57a219 Demodaten reduziert, um Controller zu testen 2024-02-06 12:34:19 +01:00
m.stangl 037ad07806 PDM-Kategorie sollte einen Eintrag haben, wenn nicht definiert 2024-02-06 10:49:35 +01:00
m.stangl 6a50eef3ed Routine zur Abfrage aller Oberflächenbehandlungen dazu 2024-02-05 22:01:20 +01:00
m.stangl 62d328b46e laden der Sivas Daten aus .csv bzw. .json impl. Check der Keys in der Logik vereinfacht. Erste Tests der Callbackroutinen beim Laden des .csv Files 2024-02-05 22:00:45 +01:00
m.stangl 745012136b einige Fixes in der gui bezüglich helbzeugfarbe und deren CAllbacks 2024-02-05 21:59:14 +01:00
m.stangl dc24a2593a Falls das Modell nach einem Key gefragt wird, den es nicht gibt, als Default none zurück 2024-02-05 21:51:33 +01:00
m.stangl f8c660e1ee Merkt sich das aktuelle Item in einer temporären json Datei im Work Ordner. Beim speichern wird der Baum ausgeblendet, da in einer neuen Session dieser neu aus der Datenbank bestimmt werden muss 2024-02-05 17:05:19 +01:00
m.stangl 1075997873 Merge branch 'main' of http://gitea.schoenenberger.de/mistangl/CreoMigrate 2024-02-05 15:24:12 +01:00
m.stangl 87da0094a7 fix: Vorher überprüfen ob die Datei lokal schon existiert. Pfad war falsch 2024-02-02 17:00:46 +01:00
42 changed files with 8058 additions and 1876 deletions
+28 -11
View File
@@ -9,27 +9,32 @@
{ {
"name": "Python: Aktuelle Datei", "name": "Python: Aktuelle Datei",
"type": "python", "type": "debugpy",
"request": "launch", "request": "launch",
"program": "${file}", "program": "${file}",
"console": "integratedTerminal", "console": "integratedTerminal",
"justMyCode": true "justMyCode": true
} },
{ {
"name": "Python: CompareLists", "name": "Python: CompareLists",
"type": "python", "type": "debugpy",
"request": "launch", "request": "launch",
"program": "${file}", "program": "${file}",
"console": "integratedTerminal", "console": "integratedTerminal",
"justMyCode": true, "justMyCode": true,
"args": [ "args": [
"-n 400102196", "400102530",
"-t" "tree",
"--local_bom",
"--local_teilestamm",
"--local_rd_ids",
"--rm_bom_ids_cfg", "C:\\Users\\s.steuer\\Documents\\Pythonprojekte\\CreoMigrate\\cfg\\BOM-Settings.cfg", "ExcludedPartnumbersInBOM",
"--rm_summary_ids_cfg", "C:\\Users\\s.steuer\\Documents\\Pythonprojekte\\CreoMigrate\\cfg\\BOM-Settings.cfg", "ExcludedPartnumbersInSummary"
], ],
} },
{ {
"name": "Python: create TOS sring", "name": "Python: create TOS sring",
"type": "python", "type": "debugpy",
"request": "launch", "request": "launch",
"program": "${file}", "program": "${file}",
"console": "integratedTerminal", "console": "integratedTerminal",
@@ -37,10 +42,10 @@
"args": [ "args": [
"--console" "--console"
], ],
} },
{ {
"name": "fetch blacklist from server", "name": "fetch blacklist from server",
"type": "python", "type": "debugpy",
"request": "launch", "request": "launch",
"program": "${file}", "program": "${file}",
"console": "integratedTerminal", "console": "integratedTerminal",
@@ -48,10 +53,10 @@
"args": [ "args": [
"--blacklist" "--blacklist"
], ],
} },
{ {
"name": "Python: Build Demo Gui", "name": "Python: Build Demo Gui",
"type": "python", "type": "debugpy",
"request": "launch", "request": "launch",
"program": "${file}", "program": "${file}",
"console": "integratedTerminal", "console": "integratedTerminal",
@@ -59,6 +64,18 @@
"args": [ "args": [
"-d" "-d"
], ],
},
{
"name": "Python: Build Real Gui",
"type": "debugpy",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal",
"justMyCode": true,
"args": [
"-s 400102196",
"--uselocal",
],
} }
] ]
} }
+54
View File
@@ -0,0 +1,54 @@
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Projektübersicht
**CreoMigrate** enthält Skripte zur Migration von Creo-Altdaten nach Solid Edge / Rule
Designer. Ziel ist es, alte 3D-Daten aus Creo mit aktuellen SIVAS-Informationen in die
neue Konstruktionsumgebung zu überführen. Der Fokus liegt auf automatisierbaren Prozessen
mit wenig Nutzereingriff (Datenbank-Abgleich, Listenvergleich, TOS-String-Erzeugung).
## Projektstruktur
```text
CreoMigrate/
├── bin/ # Nummerierte Workflow-Batch-Skripte (01..06) + GUI/Setup
├── lib/ # Python-Quellcode
├── Include/ # Zusätzliche Includes
├── cfg/ # Konfiguration
├── data/ # Datenbanken / Eingabedaten
├── doc/ # Dokumentation
├── log/ # Log-Dateien
└── work/ # Arbeitsdateien
```
## Workflow-Skripte (bin/)
Die Batch-Skripte sind in Ausführungsreihenfolge nummeriert:
1. `01_get_rd_dbase.bat` — Rule-Designer-Bestand ableiten
2. `02_get_sivas_dbase.bat` — SIVAS-Datenbank ableiten
3. `03_get_blacklist_dbase.bat` — Blacklist erzeugen
4. `04_compare_lists.bat` — Listen vergleichen
5. `05_get_sivas_teilestamm.bat` — Teilestamm aus SIVAS
6. `06_migrationsstatus_treeview.bat` — Migrationsstatus als Treeview
Weitere: `gui.bat` (GUI), `create_tos_string.bat` / `write_tos_string_to_file.bat`
(TOS-Strings), `install_py.bat`, `cremig_setenv.bat`, `get_cmd.bat`.
## Kernmodule (lib/)
- `CreoMigrateGui.py`, `gui.py`, `controller.py` — GUI + Steuerung (Tkinter)
- `compare_lists.py` — Listenvergleich
- `create_tos.py` — TOS-String-Erzeugung
- `caditem.py` — Datenmodell CAD-Item
- `update_database.py`, `manage_configs.py` — DB/Config
- `test_*.py` — Tests
## Setup
```cmd
bin\install_py.bat
```
Legt die virtuelle Umgebung an und installiert `lib/requirements.txt`.
-13
View File
@@ -1,13 +0,0 @@
{
"folders": [
{
"path": "."
}
],
"settings": {
"[python]": {
"editor.defaultFormatter": "ms-python.autopep8"
},
"python.formatting.provider": "none"
}
}
+2 -2
View File
@@ -29,5 +29,5 @@ Vorteile:
- Loslösen von Excel als Bedienumgebung, somit nicht an Version oder Hersteller gebunden. - Loslösen von Excel als Bedienumgebung, somit nicht an Version oder Hersteller gebunden.
- Problemloseres Ausrollen auf mehrere Benutzer - Problemloseres Ausrollen auf mehrere Benutzer
Installationsvoraussetzungen:
- Tabellenkalkulationsprogramm (Excel) in 64-Bit Version -> Dies ist wichtig, da unter 32-Bit das Migrationstool von Siemens (DataPrep-Tool) nicht korrekt funktioniert!
+1 -1
View File
@@ -1,5 +1,5 @@
@echo off @echo off
IF "%1" == "-s" (set SIVAS_ID=%2) else (set /p SIVAS_ID=Enter Sivas ID:) IF "%1" == "-s" (set SIVAS_ID=%2) else (set /p SIVAS_ID=Enter Sivas ID:)
CALL manage_interpreter.bat activate_interpreter CALL manage_interpreter.bat activate_interpreter
python %CREMIG_LIB%\update_database.py --sivasid=%SIVAS_ID% python %CREMIG_LIB%\update_database.py --sivasid=%SIVAS_ID% --bom
CALL manage_interpreter.bat deactivate_interpreter CALL manage_interpreter.bat deactivate_interpreter
-1
View File
@@ -1,5 +1,4 @@
@echo off @echo off
CALL 01_get_rd_dbase.bat
CALL manage_interpreter.bat activate_interpreter CALL manage_interpreter.bat activate_interpreter
python %CREMIG_LIB%\compare_lists.py %* python %CREMIG_LIB%\compare_lists.py %*
CALL manage_interpreter.bat deactivate_interpreter CALL manage_interpreter.bat deactivate_interpreter
+2 -1
View File
@@ -1,4 +1,5 @@
@echo off @echo off
IF "%1" == "-s" (set SIVAS_ID=%2) else (set /p SIVAS_ID=Enter Sivas ID or IDs:)
CALL manage_interpreter.bat activate_interpreter CALL manage_interpreter.bat activate_interpreter
python %CREMIG_LIB%\get_sivas_teilestamm.py %* python %CREMIG_LIB%\update_database.py --sivasid=%SIVAS_ID% -t
CALL manage_interpreter.bat deactivate_interpreter CALL manage_interpreter.bat deactivate_interpreter
+3 -2
View File
@@ -1,5 +1,6 @@
@echo off @echo off
CALL cremig_setenv.bat
:start :start
set /p "id=Baugruppennummer: " set /p "id=Artikelnummer: "
CALL 04_compare_lists.bat --sivasid %id% -t CALL 04_compare_lists.bat "%id%" tree --rm_bom_ids_cfg %CREMIG_CFG%\BOM-Settings.cfg ExcludedPartnumbersInBOM --rm_summary_ids_cfg %CREMIG_CFG%\BOM-Settings.cfg ExcludedPartnumbersInSummary
goto start goto start
+13 -2
View File
@@ -10,6 +10,10 @@ set CREMIG_DATA=%CREMIG%\data
set CREMIG_WORK=%CREMIG%\work set CREMIG_WORK=%CREMIG%\work
set CREMIG_LOG=%CREMIG%\log set CREMIG_LOG=%CREMIG%\log
rem Hilfsvariable um den Programmpfad zu Solid Egde immer an die aktuelle Version anzupassen. Dieser ändert sich jedesmal beim Update der Jahresversionen (Solid Edge hängt immer die Jahreszahl der Version im Ordnernamen an).
rem Deshalb muss dieser Pfad möglichst automatisch ausgelesen werden. Da auch immer das Programm Keyshot in diesem Zuge mitinstalliert wird, konnte eine Umgebungsvariable gefunden werden, die denselben Pfad verwendet wie die DataPrepUtility.exe
set SOLIDEDGE_VERSION=%KEYSHOT_EXTERNAL_LICENSE_FOLDER%
if not exist %CREMIG%\work mkdir %CREMIG%\work if not exist %CREMIG%\work mkdir %CREMIG%\work
if not exist %CREMIG%\log mkdir %CREMIG%\log if not exist %CREMIG%\log mkdir %CREMIG%\log
if not exist %CREMIG%\data mkdir %CREMIG%\data if not exist %CREMIG%\data mkdir %CREMIG%\data
@@ -27,9 +31,16 @@ set RD_DATABASE_NAME=RD_Teilenummern.csv
set BLACKLIST_DATABASE_SOURCE=\\ruledesigner\RDF_Daten\Konfigurator\CustomVaulting set BLACKLIST_DATABASE_SOURCE=\\ruledesigner\RDF_Daten\Konfigurator\CustomVaulting
set BLACKLIST_DATABASE_NAME=ERP_BOM.ini set BLACKLIST_DATABASE_NAME=ERP_BOM.ini
set VBA_MACRO_NAME=vba_format_excel.xlsm set VBA_MACRO_NAME=vba_format_excel.xlsm
set SIVAS_DATABASE_QUERY=Y:\jit\programme\Sivas2json.exe set SIVAS_BOM=Y:\jit\programme\Sivas2json.exe
set SIVAS_TEILESTAMM=\\195.243.223.3\sivas\jit\programme\KSbExcelExportSivasTeilestamm.exe set SIVAS_TEILESTAMM=\\195.243.223.3\sivas\jit\programme\KSbExcelExportSivasTeilestamm.exe
set SIVAS_EXCEL_EXPORT_DIR=%CREMIG_WORK% set SIVAS_EXCEL_EXPORT_DIR=%CREMIG_DATA%
set SIEMENS_DATA_PREP_TOOL=%SOLIDEDGE_VERSION%\DataPrepUtility.exe
set LOG_EDITOR=notepad.exe
set RD_SQL_DATABASE_CREDENTIALS=\\fileserver01\abteilungen\Entwicklung\Administration\Lizenzen\RDSQLDatabaseCredentials.bat
if exist %RD_SQL_DATABASE_CREDENTIALS% (
call %RD_SQL_DATABASE_CREDENTIALS%
)
rem Um den Python-Interpreter auf U:\ zu nutzen, Kommentar (rem) in nachfolgender Zeile entfernen rem Um den Python-Interpreter auf U:\ zu nutzen, Kommentar (rem) in nachfolgender Zeile entfernen
rem set NETWORK_INTERPRETER_PATH=\\ssg.local\freigaben\Allgemein\Programmierumgebung\Python312 rem set NETWORK_INTERPRETER_PATH=\\ssg.local\freigaben\Allgemein\Programmierumgebung\Python312
+3 -3
View File
@@ -1,6 +1,6 @@
@echo off @echo off
CALL cremig_setenv.bat CALL cremig_setenv.bat
IF NOT EXIST %CREMIG%\.venv CALL %CREMIG_BIN%\install_py.bat CALL manage_interpreter.bat activate_interpreter
CALL %CREMIG%\.venv\Scripts\activate.bat
python %CREMIG_LIB%\CreoMigrateGui.py %* python %CREMIG_LIB%\CreoMigrateGui.py %*
deactivate CALL manage_interpreter.bat deactivate_interpreter
+1
View File
@@ -17,6 +17,7 @@ deactivate
goto :eof goto :eof
:activate_interpreter_network :activate_interpreter_network
ECHO Initialisiere Python-Interpreter in %NETWORK_INTERPRETER_PATH%...
SET OLD_PATH=%PATH% SET OLD_PATH=%PATH%
SET PATH=%NETWORK_INTERPRETER_PATH%;%PATH% SET PATH=%NETWORK_INTERPRETER_PATH%;%PATH%
goto :eof goto :eof
+19
View File
@@ -0,0 +1,19 @@
@echo off
setlocal enabledelayedexpansion
REM Ermittle das aktuelle Datum im Format YYYY-MM-DD
for /f "delims=" %%a in ('powershell Get-Date -Format "yyyy_MM_dd"') do set datetime=%%a
set "Namensanfang=TOS-Gruppenstring_"
set "Dateiname=%Namensanfang%!datetime!.txt"
REM Führe die folgende .bat aus mit dem gesetzten Schalter -o um eine Datei mit dem Code zu generieren
CALL %CREMIG_BIN%\create_tos_string.bat -o %Dateiname%
echo Die Datei wurde in %CREMIG_WORK% mit dem Namen: %Dateiname% gespeichert
echo Bitte pflegen sie den Inhalt dieser Datei in die jeweiligen CampiEsterni.ini unter CALC LINK10 ein.
echo:
endlocal
pause
+16 -14
View File
@@ -1,4 +1,5 @@
[Kategorien] [Kategorien]
<undefiniert>
Baugruppe Baugruppe
Einzelteil Einzelteil
Kaufteil Kaufteil
@@ -58,35 +59,36 @@ Aluminium
Stahl Stahl
[Fertigungsart]: [Fertigungsart]:
3D-drucken 3D - 3D drucken
biegen BI - biegen
drehen DR - drehen
extrudieren EX - extrudieren
fräsen FR - fräsen
gießen GI - gießen
laser-/wasserstrahlschneiden LW - laser- und wasserstrahlschneiden
sägen SA - sägen
schweißen SW - schweißen
spritzgießen SP - spritzgießen
stanzen ST - stanzen
strangpressen SN - strangpressen
[Beschaffungsart] [Beschaffungsart]
Eigenbau Eigenbau
Kaufteil Kaufteil
[Ruestcode] [Ruestcode]
Trümmerbaugruppe
HZS Halbzeuge Sägeteile HZS Halbzeuge Sägeteile
SRC Standard Rüstcode SRC Standard Rüstcode
Trümmerbaugruppe
[RuestcodeStandard] [RuestcodeStandard]
HZS Halbzeuge Sägeteile HZS Halbzeuge Sägeteile
SRC Standard Rüstcode SRC Standard Rüstcode
[RuestcodeBaugruppe] [RuestcodeBaugruppe]
SRC Standard Rüstcode
Trümmerbaugruppe Trümmerbaugruppe
SRC Standard Rüstcode
[Halbzeug] [Halbzeug]
WAHR WAHR
+14
View File
@@ -0,0 +1,14 @@
[ExcludedPartnumbersInBOM]
#============================================================================================================================
# Teilenummern, die in der Migrationsübersicht (u.a. im Baum von CreoMigrate) nicht dargestellt sein sollen
#============================================================================================================================
MA0000008
MA0000005
[ExcludedPartnumbersInSummary]
#============================================================================================================================
# Teilenummern, die in der Zusammenfassung der Migrationsübersicht nicht enthalten sein sollen
# Wenn die Nummer bereits in der Sektion "ExcludedPartnumbersInBOM" enthalten ist, muss sie hier nicht nochmal aufgelistet werden
#============================================================================================================================
+4
View File
@@ -1,4 +1,5 @@
[Farbauswahl] [Farbauswahl]
PANTONE 2175 C
RAL 1004 Goldgelb RAL 1004 Goldgelb
RAL 2000 Gelborange RAL 2000 Gelborange
RAL 3002 Kaminrot RAL 3002 Kaminrot
@@ -21,6 +22,9 @@ Grau
Rot Rot
Grün Grün
Blau Blau
siehe Oben
Ocker
Transparent
[FarbeEloxieren] [FarbeEloxieren]
Rot Rot
+64 -19
View File
@@ -1,6 +1,6 @@
[Fertigungsarten] [Fertigungsarten]
3D - 3D drucken=3D-drucken 3D - 3D-drucken=3D-drucken
BI - biegen=biegen BI - biegen=biegen
DR - drehen=drehen DR - drehen=drehen
EX - extrudieren=extrudieren EX - extrudieren=extrudieren
@@ -15,19 +15,19 @@ ST - stanzen=stanzen
SW - schweißen=schweißen SW - schweißen=schweißen
[FertigungsartenBaugruppe] [FertigungsartenBaugruppe]
biegen BI - biegen
drehen DR - drehen
fräsen FR - fräsen
laser-/wasserstrahlschneiden LW - laser- und wasserstrahlschneiden
stanzen ST - stanzen
sägen SA - sägen
[FertigungsartSchweissbaugruppe] [FertigungsartSchweissbaugruppe]
schweißen SW - schweißen
[FertigungsartenAllgemeintoleranzenMapping] [FertigungsartenAllgemeintoleranzenMapping]
3D - 3D drucken=Allgemeintoleranz3DDruck 3D - 3D-drucken=Allgemeintoleranz3DDruck
BI - biegen=AllgemeintoleranzSpanen BI - biegen=AllgemeintoleranzBiegen
DR - drehen=AllgemeintoleranzSpanen DR - drehen=AllgemeintoleranzSpanen
EX - extrudieren=AllgemeintoleranzExtrudieren EX - extrudieren=AllgemeintoleranzExtrudieren
FR - fräsen=AllgemeintoleranzSpanen FR - fräsen=AllgemeintoleranzSpanen
@@ -40,6 +40,20 @@ SP - spritzgießen=AllgemeintoleranzSpritzgiessen
ST - stanzen=AllgemeintoleranzStanzen ST - stanzen=AllgemeintoleranzStanzen
SW - schweißen=AllgemeintoleranzSchweissen SW - schweißen=AllgemeintoleranzSchweissen
[AllgemeintoleranzSpanen]
ISO 2768:1991-fH
ISO 2768:1991-fK
ISO 2768:1991-fL
ISO 2768:1991-mH
ISO 2768:1991-mK
ISO 2768:1991-mL
ISO 2768:1991-cH
ISO 2768:1991-cK
ISO 2768:1991-cL
ISO 2768:1991-vH
ISO 2768:1991-vK
ISO 2768:1991-vL
[AllgemeintoleranzBaugruppe] [AllgemeintoleranzBaugruppe]
ISO 2768:1991-fH ISO 2768:1991-fH
ISO 2768:1991-fK ISO 2768:1991-fK
@@ -105,15 +119,15 @@ EN ISO 13920-DG
EN ISO 13920-DH EN ISO 13920-DH
[AllgemeintoleranzSpritzgiessen] [AllgemeintoleranzSpritzgiessen]
ISO 20457 - TG1 DIN ISO 20457-TG1
ISO 20457 - TG2 DIN ISO 20457-TG2
ISO 20457 - TG3 DIN ISO 20457-TG3
ISO 20457 - TG4 DIN ISO 20457-TG4
ISO 20457 - TG5 DIN ISO 20457-TG5
ISO 20457 - TG6 DIN ISO 20457-TG6
ISO 20457 - TG7 DIN ISO 20457-TG7
ISO 20457 - TG8 DIN ISO 20457-TG8
ISO 20457 - TG9 DIN ISO 20457-TG9
[AllgemeintoleranzStanzen] [AllgemeintoleranzStanzen]
DIN 6930-2 - f DIN 6930-2 - f
@@ -129,3 +143,34 @@ DIN 16941 - 2A
DIN 16941 - 2B DIN 16941 - 2B
DIN 16941 - 3A DIN 16941 - 3A
DIN 16941 - 3B DIN 16941 - 3B
[AllgemeintoleranzVerpressen]
ISO 2768:1991-fH
ISO 2768:1991-fK
ISO 2768:1991-fL
ISO 2768:1991-mH
ISO 2768:1991-mK
ISO 2768:1991-mL
ISO 2768:1991-cH
ISO 2768:1991-cK
ISO 2768:1991-cL
ISO 2768:1991-vH
ISO 2768:1991-vK
ISO 2768:1991-vL
[AllgemeintoleranzBiegen]
ISO 2768:1991-fH
ISO 2768:1991-fK
ISO 2768:1991-fL
ISO 2768:1991-mH
ISO 2768:1991-mK
ISO 2768:1991-mL
ISO 2768:1991-cH
ISO 2768:1991-cK
ISO 2768:1991-cL
ISO 2768:1991-vH
ISO 2768:1991-vK
ISO 2768:1991-vL
DIN 2194 - G1
DIN 2194 - G2
DIN 2194 - G3
+2362
View File
File diff suppressed because it is too large Load Diff
+1
View File
@@ -0,0 +1 @@
\,?,|,!,@,à,è,ì,ò,ù,£,$,%,;
+221 -32
View File
@@ -1,8 +1,32 @@
{ {
"VA": {
"Werkstoff": "false",
"Message": "Bitte individuell wählen!"
},
"1.4301": { "1.4301": {
"Werkstoff": "1.4301 (X5CrNi18-10)", "Werkstoff": "1.4301 (X5CrNi18-10)",
"Werkstofftyp": "Stahl" "Werkstofftyp": "Stahl"
}, },
"X5CrNi18-10": {
"Werkstoff": "1.4301 (X5CrNi18-10)",
"Werkstofftyp": "Stahl"
},
"1.4301 (X5CrNi18-10)": {
"Werkstoff": "1.4301 (X5CrNi18-10)",
"Werkstofftyp": "Stahl"
},
"1.4301f / 59381": {
"Werkstoff": "1.4301 (X5CrNi18-10)",
"Werkstofftyp": "Stahl"
},
"X5CrNi 18-10": {
"Werkstoff": "1.4301 (X5CrNi18-10)",
"Werkstofftyp": "Stahl"
},
"X5CrNi 18-9": {
"Werkstoff": "1.4301 (X5CrNi18-10)",
"Werkstofftyp": "Stahl"
},
"1.4305": { "1.4305": {
"Werkstoff": "1.4305 (X8CrNiS18-9)", "Werkstoff": "1.4305 (X8CrNiS18-9)",
"Werkstofftyp": "Stahl" "Werkstofftyp": "Stahl"
@@ -15,10 +39,42 @@
"Werkstoff": "1.4305 (X8CrNiS18-9)", "Werkstoff": "1.4305 (X8CrNiS18-9)",
"Werkstofftyp": "Stahl" "Werkstofftyp": "Stahl"
}, },
"X10CrNiS 18-9": {
"Werkstoff": "1.4305 (X8CrNiS18-9)",
"Werkstofftyp": "Stahl"
},
"X8CrNiS 18-9": {
"Werkstoff": "1.4305 (X8CrNiS18-9)",
"Werkstofftyp": "Stahl"
},
"X8CrNiS18-9": {
"Werkstoff": "1.4305 (X8CrNiS18-9)",
"Werkstofftyp": "Stahl"
},
"X12CrNi17 7": {
"Werkstoff": "1.4310 (X10CrNi18-8)",
"Werkstofftyp": "Stahl"
},
"Aluminium": {
"Werkstoff": "false",
"Message": "Bitte individuell wählen!"
},
"AlCuMgPb": {
"Werkstoff": "EN AW-2007 (3.1645)",
"Werkstofftyp": "Aluminium"
},
"3.3206.72": { "3.3206.72": {
"Werkstoff": "EN AW-6063-T66", "Werkstoff": "EN AW-6063-T66",
"Werkstofftyp": "Aluminium" "Werkstofftyp": "Aluminium"
}, },
"AlSiMg 0,5 F25": {
"Werkstoff": "EN AW-6063-T66",
"Werkstofftyp": "Aluminium"
},
"F25": {
"Werkstoff": "EN AW-6063-T66",
"Werkstofftyp": "Aluminium"
},
"AlMgSi0.5": { "AlMgSi0.5": {
"Werkstoff": "EN AW-6060 (3.3206)", "Werkstoff": "EN AW-6060 (3.3206)",
"Werkstofftyp": "Aluminium" "Werkstofftyp": "Aluminium"
@@ -27,21 +83,41 @@
"Werkstoff": "EN AW-6060 (3.3206)", "Werkstoff": "EN AW-6060 (3.3206)",
"Werkstofftyp": "Aluminium" "Werkstofftyp": "Aluminium"
}, },
"AlMgSi 0.5": {
"Werkstoff": "EN AW-6060 (3.3206)",
"Werkstofftyp": "Aluminium"
},
"AlMgSi0.5 F22": {
"Werkstoff": "EN AW-6060-T66 (3.3206-T66)",
"Werkstofftyp": "Aluminium"
},
"AlSiMg 0,5 F22": { "AlSiMg 0,5 F22": {
"Werkstoff": "EN AW-6060-T66 (3.3206-T66)", "Werkstoff": "EN AW-6060-T66 (3.3206-T66)",
"Werkstofftyp": "Aluminium" "Werkstofftyp": "Aluminium"
}, },
"AlSiMg 0,5 F25": { "AlMg3": {
"Werkstoff": "EN AW-6063-T66", "Werkstoff": "EN AW-5754 (3.3535)",
"Werkstofftyp": "Aluminium" "Werkstofftyp": "Aluminium"
}, },
"St": {
"Werkstoff": "false",
"Message": "Bitte individuell wählen!"
},
"C45": { "C45": {
"Werkstoff": "1.0503 (C45)", "Werkstoff": "1.0503 (C45)",
"Werkstofftyp": "Stahl" "Werkstofftyp": "Stahl"
}, },
"F25": { "Ck60": {
"Werkstoff": "EN AW-6063-T66", "Werkstoff": "1.1221 (C60E)",
"Werkstofftyp": "Aluminium" "Werkstofftyp": "Stahl"
},
"S355JO": {
"Werkstoff": "1.0553 (S355J0)",
"Werkstofftyp": "Stahl"
},
"1.0038 (S235JR)": {
"Werkstoff": "1.0038 (S235JR)",
"Werkstofftyp": "Stahl"
}, },
"S235JR": { "S235JR": {
"Werkstoff": "1.0038 (S235JR)", "Werkstoff": "1.0038 (S235JR)",
@@ -51,14 +127,6 @@
"Werkstoff": "1.0038 (S235JR)", "Werkstoff": "1.0038 (S235JR)",
"Werkstofftyp": "Stahl" "Werkstofftyp": "Stahl"
}, },
"S235JRG2C": {
"Werkstoff": "1.0122 (S235JRC)",
"Werkstofftyp": "Stahl"
},
"S235JRG2C+C": {
"Werkstoff": "1.0122 (S235JRC)",
"Werkstofftyp": "Stahl"
},
"St-37": { "St-37": {
"Werkstoff": "1.0038 (S235JR)", "Werkstoff": "1.0038 (S235JR)",
"Werkstofftyp": "Stahl" "Werkstofftyp": "Stahl"
@@ -67,40 +135,161 @@
"Werkstoff": "1.0038 (S235JR)", "Werkstoff": "1.0038 (S235JR)",
"Werkstofftyp": "Stahl" "Werkstofftyp": "Stahl"
}, },
"X5CrNi18-10": { "S235 JR": {
"Werkstoff": "1.4301 (X5CrNi18-10)", "Werkstoff": "1.0038 (S235JR)",
"Werkstofftyp": "Stahl" "Werkstofftyp": "Stahl"
}, },
"X8CrNiS 18-9": { "S235JR galv. verzinkt Fe/Zn 8-15 B": {
"Werkstoff": "1.4305 (X8CrNiS18-9)", "Werkstoff": "1.0038 (S235JR)",
"Werkstofftyp": "Stahl",
"Oberfläche": "verzinken"
},
"S235JR+Cr": {
"Werkstoff": "1.0038+CR (S235JR+CR)",
"Werkstofftyp": "Stahl" "Werkstofftyp": "Stahl"
}, },
"X8CrNiS18-9": { "S235JRG2C": {
"Werkstoff": "1.4305 (X8CrNiS18-9)", "Werkstoff": "1.0122 (S235JRC)",
"Werkstofftyp": "Stahl" "Werkstofftyp": "Stahl"
}, },
"1.4301 (X5CrNi18-10)": { "S235JRG2C+C": {
"Werkstoff": "1.4301 (X5CrNi18-10)", "Werkstoff": "1.0122 (S235JRC)",
"Werkstofftyp": "Stahl" "Werkstofftyp": "Stahl"
}, },
"S235JRC": {
"Werkstoff": "1.0122 (S235JRC)",
"Werkstofftyp": "Stahl"
},
"Kunststo": {
"Werkstoff": "false",
"Message": "Bitte individuell wählen!"
},
"PA6 GF30": { "PA6 GF30": {
"Werkstoff": "PA 6 GF 30", "Werkstoff": "PA 6 GF 30",
"Werkstofftyp": "Kunst-/ Verbundstoff", "Werkstofftyp": "Kunst-/ Verbundstoff",
"Oberfläche": "Masterbatch (Grundfarbe)" "Oberfläche": "Masterbatch (Grundfarbe)"
}, },
"S235JR galv. verzinkt Fe/Zn 8-15 B": { "PA 6 GF 30 Regranulat schwarz": {
"Werkstoff": "1.0038 (S235JR) ", "Werkstoff": "PA 6 GF 30 (REC)",
"Werkstofftyp": "Stahl", "Werkstofftyp": "Kunst-/ Verbundstoff",
"Oberfläche": "verzinken" "Oberfläche": "Masterbatch (Grundfarbe)"
},
"VA": {
"Werkstoff": "false",
"Message": "Bitte individuell wählen!"
}, },
"PA6 GF30; Farbe ähnlich RAL 5015": { "PA6 GF30; Farbe ähnlich RAL 5015": {
"Werkstoff": "PA 6 GF 30", "Werkstoff": "PA 6 GF 30",
"Werkstofftyp": "Kunst-/ Verbundstoff", "Werkstofftyp": "Kunst-/ Verbundstoff",
"Oberfläche":"Masterbatch (Grundfarbe)", "Oberfläche": "Masterbatch (Grundfarbe)",
"Farbe": "RAL 5015" "Farbe": "RAL 5015 Himmelblau"
} },
"PA6 30% GF / RAL 7035": {
"Werkstoff": "PA 6 GF 30",
"Werkstofftyp": "Kunst-/ Verbundstoff",
"Oberfläche": "Masterbatch (Grundfarbe)",
"Farbe": "RAL 7035 Lichtgrau"
},
"PA6 30% GF ": {
"Werkstoff": "PA 6 GF 30",
"Werkstofftyp": "Kunst-/ Verbundstoff",
"Oberfläche": "Masterbatch (Grundfarbe)"
},
"PA 66 GF 50": {
"Werkstoff": "PA 66 GF 50",
"Werkstofftyp": "Kunst-/ Verbundstoff",
"Oberfläche": "Masterbatch (Grundfarbe)"
},
"PC GF 10": {
"Werkstoff": "PC GF 10",
"Werkstofftyp": "Kunst-/ Verbundstoff",
"Oberfläche": "Masterbatch (Grundfarbe)"
},
"POM schw": {
"Werkstoff": "POM",
"Werkstofftyp": "Kunst-/ Verbundstoff",
"Oberfläche": "Masterbatch (Grundfarbe)",
"Farbe": "Schwarz"
},
"POM schwarz": {
"Werkstoff": "POM",
"Werkstofftyp": "Kunst-/ Verbundstoff",
"Oberfläche": "Masterbatch (Grundfarbe)",
"Farbe": "Schwarz"
},
"POM sch": {
"Werkstoff": "POM",
"Werkstofftyp": "Kunst-/ Verbundstoff",
"Oberfläche": "Masterbatch (Grundfarbe)",
"Farbe": "Schwarz"
},
"POM weiß": {
"Werkstoff": "POM",
"Werkstofftyp": "Kunst-/ Verbundstoff",
"Oberfläche": "Masterbatch (Grundfarbe)",
"Farbe": "Weiß"
},
"POM natur": {
"Werkstoff": "POM",
"Werkstofftyp": "Kunst-/ Verbundstoff",
"Oberfläche": "Masterbatch (Grundfarbe)",
"Farbe": "Natur"
},
"POM": {
"Werkstoff": "POM",
"Werkstofftyp": "Kunst-/ Verbundstoff",
"Oberfläche": "Masterbatch (Grundfarbe)"
},
"POM ": {
"Werkstoff": "POM",
"Werkstofftyp": "Kunst-/ Verbundstoff",
"Oberfläche": "Masterbatch (Grundfarbe)"
},
"POM ": {
"Werkstoff": "POM",
"Werkstofftyp": "Kunst-/ Verbundstoff",
"Oberfläche": "Masterbatch (Grundfarbe)"
},
"PUR D44 ": {
"Werkstoff": "Bitte individuell wählen!",
"Werkstofftyp": "Kunst-/ Verbundstoff",
"Oberfläche": "Masterbatch (Grundfarbe)",
"Farbe": "Bitte individuell wählen!"
},
"-": {
"Werkstoff": "false",
"Message": "Bitte individuell wählen!"
},
"Al": {
"Werkstoff": "false",
"Message": "Bitte individuell wählen!"
},
"-----": {
"Werkstoff": "false",
"Message": "Bitte individuell wählen!"
},
"---": {
"Werkstoff": "false",
"Message": "Bitte individuell wählen!"
},
"----": {
"Werkstoff": "false",
"Message": "Bitte individuell wählen!"
},
"--- / ---": {
"Werkstoff": "false",
"Message": "Bitte individuell wählen!"
},
"--- / 2391": {
"Werkstoff": "false",
"Message": "Bitte individuell wählen!"
},
"--- / 444": {
"Werkstoff": "false",
"Message": "Bitte individuell wählen!"
},
"--- / EN 24017": {
"Werkstoff": "false",
"Message": "Bitte individuell wählen!"
},
"Federsta": {
"Werkstoff": "false",
"Message": "Bitte individuell wählen!"
}
} }
-1
View File
@@ -3,7 +3,6 @@ ISO 13715
[Oberflaechennorm] [Oberflaechennorm]
ISO 1302:2002 ISO 1302:2002
ISO 21920
[Massnorm] [Massnorm]
ISO 14405 ISO 14405
+12
View File
@@ -29,6 +29,16 @@ verzinken
blank blank
phosphatieren phosphatieren
[Schweissbaugruppe]
lackieren
pulverbeschichten
verzinken
vernickeln
brünieren
härten
bürsten
sandstrahlen
[Oberflaechenbehandlungen] [Oberflaechenbehandlungen]
Masterbatch (Grundfarbe) Masterbatch (Grundfarbe)
blank blank
@@ -43,3 +53,5 @@ pulverbeschichten
sandstrahlen sandstrahlen
vernickeln vernickeln
verzinken verzinken
+16
View File
@@ -0,0 +1,16 @@
[Status]
0=VERFÜGBAR
1=IN BEARBEITUNG
2=IN ÜBERARBEITUNG
3=FREIGEGEBEN
4=FREIGEGEBEN
10=VORLÄUFIG
11=PROTOTYP
12=IN PRÜFUNG
13=UNGÜLTIG
101=BAGATELLÄNDERUNG
102=REVISION VERFÜGBAR
103=ZUR PRÜFUNG
104=REVISION IN PRÜFUNG
105=REVISION ZUR PRÜFUNG
106=GESPERRT
+125 -47
View File
@@ -6,7 +6,7 @@
"0": "Intern/Referenzgruppe", "0": "Intern/Referenzgruppe",
"1": "Halbzeug", "1": "Halbzeug",
"2": "Verkaufsprodukte", "2": "Verkaufsprodukte",
"3": "Schönenberger Produkte", "3": "Schönenberger Produkt",
"4": "Automation", "4": "Automation",
"5": "Maschinenelement", "5": "Maschinenelement",
"6": "Schönenberger Komponenten", "6": "Schönenberger Komponenten",
@@ -28,6 +28,7 @@
}, },
"TOS_Schoenenberger_Produkt": { "TOS_Schoenenberger_Produkt": {
"TOS-level": 2, "TOS-level": 2,
"_comment" : "3 - Schönenberger Produkt",
"children": { "children": {
"30": "ILS IntraLogistikSystem", "30": "ILS IntraLogistikSystem",
"31": "MAS Mittenabgehängtes System - OMNIFLO", "31": "MAS Mittenabgehängtes System - OMNIFLO",
@@ -52,6 +53,7 @@
}, },
"TOS_ILS": { "TOS_ILS": {
"TOS-level": 3, "TOS-level": 3,
"_comment" : "30 - Schönenberger Produkt -> ILS IntraLogistikSystem",
"children": { "children": {
"300": "ILS 2.0", "300": "ILS 2.0",
"301": "ILS 3.0", "301": "ILS 3.0",
@@ -62,48 +64,9 @@
"302": "TOS_ILS_Foerderer" "302": "TOS_ILS_Foerderer"
} }
}, },
"TOS_ILS_Foerderer": {
"TOS-level": 4,
"children": {
"3020": "ETF"
},
"reference-ids": {}
},
"TOS_MAS": {
"TOS-level": 3,
"children": {
"310": "Fahrstrecke",
"311": "Ein- und Anbaugruppe für Omniflo System",
"312": "Verbinder und Kleinteil",
"313": "Baugruppe für Aktionen an/mit Trolleys",
"314": "Förderer"
},
"reference-ids": {
"310": "TOS_MAS_Fahrstrecke"
}
},
"TOS_Spinnereikomponente": {
"TOS-level": 3,
"children": {
"320": "Hülsenreiniger automatisch",
"321": "Hülsenreiniger manuell",
"322": "Reibradantrieb RA"
},
"reference-ids": {}
},
"TOS_Betriebsmittel": {
"TOS-level": 3,
"children": {
"330": "Trolley Standard",
"331": "Trolley Projekte"
},
"reference-ids": {
"330": "TOS_Trolley",
"331": "TOS_Trolley_Projekte"
}
},
"TOS_ILS_2": { "TOS_ILS_2": {
"TOS-level": 4, "TOS-level": 4,
"_comment" : "300 - Schönenberger Produkt -> ILS IntraLogistikSystem -> ILS 2.0",
"children": { "children": {
"3000": "Modul", "3000": "Modul",
"3001": "Modul-Komponente", "3001": "Modul-Komponente",
@@ -114,8 +77,31 @@
}, },
"reference-ids": {} "reference-ids": {}
}, },
"TOS_MAS_Fahrstrecke": { "TOS_ILS_Foerderer": {
"TOS-level": 4, "TOS-level": 4,
"_comment" : "302 - Schönenberger Produkt -> ILS IntraLogistikSystem -> Förderer",
"children": {
"3020": "ETF"
},
"reference-ids": {}
},
"TOS_MAS": {
"TOS-level": 3,
"_comment" : "31 - Schönenberger Produkt -> MAS Mittenabgehängtes System - OMNIFLO",
"children": {
"310": "Fahrstrecke",
"311": "Ein- und Anbaugruppe für Omniflo System",
"312": "Verbinder und Kleinteil",
"313": "Baugruppe für Aktionen an/mit Trolleys",
"314": "Förderer"
},
"reference-ids": {
"310": "TOS_MAS_Fahrstecke"
}
},
"TOS_MAS_Fahrstecke": {
"TOS-level": 4,
"_comment" : "310 - Schönenberger Produkt -> MAS Mittenabgehängtes System - OMNIFLO -> Fahrstrecke",
"children": { "children": {
"3100": "Aluschiene", "3100": "Aluschiene",
"3101": "Bogen", "3101": "Bogen",
@@ -127,8 +113,31 @@
}, },
"reference-ids": {} "reference-ids": {}
}, },
"TOS_Trolley": { "TOS_Spinnereikomponente": {
"TOS-level": 3,
"_comment" : "32 - Schönenberger Produkt -> Spinnereikomponente",
"children": {
"320": "Hülsenreiniger automatisch",
"321": "Hülsenreiniger manuell",
"322": "Reibradantrieb RA"
},
"reference-ids": {}
},
"TOS_Betriebsmittel": {
"TOS-level": 3,
"_comment" : "33 - Schönenberger Produkt -> Betriebsmittel",
"children": {
"330": "Trolley Standard",
"331": "Trolley Projekte"
},
"reference-ids": {
"330": "TOS_Trolley",
"331": "TOS_Trolley_Projekte"
}
},
"TOS_Trolley": {
"TOS-level": 4, "TOS-level": 4,
"_comment" : "330 - Schönenberger Produkt -> Betriebsmittel -> Trolley Standard",
"children": { "children": {
"3300": "Omniflo", "3300": "Omniflo",
"3301": "Spinnerei", "3301": "Spinnerei",
@@ -144,6 +153,7 @@
}, },
"TOS_Trolley_Omniflo": { "TOS_Trolley_Omniflo": {
"TOS-level": 5, "TOS-level": 5,
"_comment" : "3300 - Schönenberger Produkt -> Betriebsmittel -> Trolley Standard -> Omniflo",
"children": { "children": {
"33000": "Trolley-V", "33000": "Trolley-V",
"33001": "Trolley Hängeware", "33001": "Trolley Hängeware",
@@ -157,6 +167,7 @@
}, },
"TOS_Trolley_Spinnerei": { "TOS_Trolley_Spinnerei": {
"TOS-level": 5, "TOS-level": 5,
"_comment" : "3301 - Schönenberger Produkt -> Betriebsmittel -> Trolley Standard -> Spinnerei",
"children": { "children": {
"33010": "Spulenzug", "33010": "Spulenzug",
"33011": "Zubehör" "33011": "Zubehör"
@@ -165,6 +176,7 @@
}, },
"TOS_Trolley_ILS": { "TOS_Trolley_ILS": {
"TOS-level": 5, "TOS-level": 5,
"_comment" : "3302 - Schönenberger Produkt -> Betriebsmittel -> Trolley Standard -> ILS",
"children": { "children": {
"33020": "Single carrier SC", "33020": "Single carrier SC",
"33021": "Minitrolley MT", "33021": "Minitrolley MT",
@@ -174,6 +186,7 @@
}, },
"TOS_Trolley_Projekte": { "TOS_Trolley_Projekte": {
"TOS-level": 4, "TOS-level": 4,
"_comment" : "331 - Schönenberger Produkt -> Betriebsmittel -> Trolley Projekte",
"children": { "children": {
"3310": "Liegeware", "3310": "Liegeware",
"3311": "diverse Anwendungen", "3311": "diverse Anwendungen",
@@ -185,6 +198,7 @@
}, },
"TOS_Geruest": { "TOS_Geruest": {
"TOS-level": 3, "TOS-level": 3,
"_comment" : "34 - Schönenberger Produkt -> Gerüst",
"children": { "children": {
"340": "Rohrträger", "340": "Rohrträger",
"341": "Abhänger", "341": "Abhänger",
@@ -198,6 +212,7 @@
}, },
"TOS_FremdTransport": { "TOS_FremdTransport": {
"TOS-level": 3, "TOS-level": 3,
"_comment" : "35 - Schönenberger Produkt -> Fremd-Transportsysteme & SSG-Anbauten",
"children": { "children": {
"350": "PIN & Klinke", "350": "PIN & Klinke",
"351": "CDDC", "351": "CDDC",
@@ -207,6 +222,7 @@
}, },
"TOS_MAS_Konfig": { "TOS_MAS_Konfig": {
"TOS-level": 3, "TOS-level": 3,
"_comment" : "36 - Schönenberger Produkt -> Förderer MAS aktuell Konfiguration",
"children": { "children": {
"360": "Farbe / EL / H" "360": "Farbe / EL / H"
}, },
@@ -214,6 +230,7 @@
}, },
"TOS_Automation": { "TOS_Automation": {
"TOS-level": 2, "TOS-level": 2,
"_comment" : "4 - Automation",
"children": { "children": {
"40": "Schaltschrank", "40": "Schaltschrank",
"41": "Schaltschrank Einbaumaterial", "41": "Schaltschrank Einbaumaterial",
@@ -221,7 +238,7 @@
"43": "Sensorik", "43": "Sensorik",
"44": "Kabel", "44": "Kabel",
"45": "Installationsmaterial", "45": "Installationsmaterial",
"46": "Frei", "46": "Divers",
"47": "Frei", "47": "Frei",
"48": "Frei", "48": "Frei",
"49": "Sonstiges" "49": "Sonstiges"
@@ -233,11 +250,13 @@
"43": "TOS_Automation_Sensorik", "43": "TOS_Automation_Sensorik",
"44": "TOS_Kabel", "44": "TOS_Kabel",
"45": "TOS_Installation", "45": "TOS_Installation",
"46": "TOS_Auto_Divers",
"49": "TOS_Automation_Sonstiges" "49": "TOS_Automation_Sonstiges"
} }
}, },
"TOS_Schaltschrank": { "TOS_Schaltschrank": {
"TOS-level": 3, "TOS-level": 3,
" _comment" : "40 - Automation -> Schaltschrank",
"children": { "children": {
"400": "Stand Schaltschrank", "400": "Stand Schaltschrank",
"401": "Kompakt Schaltschrank", "401": "Kompakt Schaltschrank",
@@ -250,6 +269,7 @@
}, },
"TOS_Schalt_Einbau": { "TOS_Schalt_Einbau": {
"TOS-level": 3, "TOS-level": 3,
"_comment" : "41 - Automation -> Schaltschrank Einbaumaterial",
"children": { "children": {
"410": "Einbaumaterial", "410": "Einbaumaterial",
"411": "Netzteil", "411": "Netzteil",
@@ -261,18 +281,32 @@
"417": "Motorschutzschalter", "417": "Motorschutzschalter",
"418": "Frequenzumrichter" "418": "Frequenzumrichter"
}, },
"reference-ids": {
"414": "TOS_SchaltEin_Netz"
}
},
"TOS_SchaltEin_Netz": {
"TOS-level": 4,
"_comment" : "414 - Automation -> Schaltschrank Einbaumaterial -> Netzwerk Komponente",
"children": {
"4140": "managed Switch",
"4141": "unmanaged Switch",
"4142": "VPN-Router"
},
"reference-ids": {} "reference-ids": {}
}, },
"TOS_Dezentral": { "TOS_Dezentral": {
"TOS-level": 3, "TOS-level": 3,
"_comment" : "42 - Automation -> Dezentrale Hardware",
"children": { "children": {
"420": "Bedientableau", "420": "Bedientableau",
"421": "I/O - Modul IP65/IP67" "421": "Modul IP65/IP67"
}, },
"reference-ids": {} "reference-ids": {}
}, },
"TOS_Automation_Sensorik": { "TOS_Automation_Sensorik": {
"TOS-level": 3, "TOS-level": 3,
"_comment" : "43 - Automation -> Sensorik",
"children": { "children": {
"430": "Induktiv", "430": "Induktiv",
"431": "Optisch", "431": "Optisch",
@@ -285,20 +319,46 @@
"438": "Reedkontakte", "438": "Reedkontakte",
"439": "Scanner / Kamera" "439": "Scanner / Kamera"
}, },
"reference-ids": {
"439": "TOS_Auto_Sens_ScaKa"
}
},
"TOS_Auto_Sens_ScaKa": {
"TOS-level": 4,
"_comment" : "439 - Automation -> Sensorik -> Scanner / Kamera",
"children": {
"4390": "Camera",
"4391": "Scanner",
"4392": "Handscanner"
},
"reference-ids": {} "reference-ids": {}
}, },
"TOS_Kabel": { "TOS_Kabel": {
"TOS-level": 3, "TOS-level": 3,
"_comment" : "44 - Automation -> Kabel",
"children": { "children": {
"440": "Steuerleitung", "440": "Steuerleitung",
"441": "Anschlussleitung", "441": "Anschlussleitung",
"442": "Feldbusleitung", "442": "Feldbusleitung",
"443": "Zubehör" "443": "Zubehör"
}, },
"reference-ids": {
"440": "TOS_Auto_Kabel_Steuer"
}
},
"TOS_Auto_Kabel_Steuer": {
"TOS-level": 4,
"_comment" : "440 - Automation -> Kabel -> Steuerleitung",
"children": {
"4400": "Geschirmt",
"4401": "Nummeriert",
"4402": "UL/CSA"
},
"reference-ids": {} "reference-ids": {}
}, },
"TOS_Installation": { "TOS_Installation": {
"TOS-level": 3, "TOS-level": 3,
"_comment" : "45 - Automation -> Installationsmaterial",
"children": { "children": {
"450": "Kabelpritsche", "450": "Kabelpritsche",
"451": "Kabelkanal", "451": "Kabelkanal",
@@ -307,8 +367,17 @@
}, },
"reference-ids": {} "reference-ids": {}
}, },
"TOS_Auto_Divers": {
"TOS-level": 3,
"_comment" : "46 - Automation -> Divers",
"children": {
"460": "Auswahl Lichttaster"
},
"reference-ids": {}
},
"TOS_Automation_Sonstiges": { "TOS_Automation_Sonstiges": {
"TOS-level": 3, "TOS-level": 3,
"_comment" : "49 - Automation -> Sonstiges",
"children": { "children": {
"490": "Beschriftung", "490": "Beschriftung",
"491": "Schüttgut" "491": "Schüttgut"
@@ -317,6 +386,7 @@
}, },
"TOS_Maschinenelement": { "TOS_Maschinenelement": {
"TOS-level": 2, "TOS-level": 2,
"_comment" : "5 - Maschinenelement",
"children": { "children": {
"50": "Verbindungselement", "50": "Verbindungselement",
"51": "Lager", "51": "Lager",
@@ -338,6 +408,7 @@
}, },
"TOS_Verbindungselement": { "TOS_Verbindungselement": {
"TOS-level": 3, "TOS-level": 3,
"_comment" : "50 - Maschinenelement -> Verbindungselement",
"children": { "children": {
"500": "Schraube", "500": "Schraube",
"501": "Mutter", "501": "Mutter",
@@ -352,6 +423,7 @@
}, },
"TOS_Lager": { "TOS_Lager": {
"TOS-level": 3, "TOS-level": 3,
"_comment" : "51 - Maschinenelement -> Lager",
"children": { "children": {
"510": "Gleitlager", "510": "Gleitlager",
"511": "Wälzlager" "511": "Wälzlager"
@@ -360,6 +432,7 @@
}, },
"TOS_Kraft_Drehmoment": { "TOS_Kraft_Drehmoment": {
"TOS-level": 3, "TOS-level": 3,
"_comment" : "52 - Maschinenelement -> Kraft-/Drehmomentübertragungselement",
"children": { "children": {
"520": "Zahntriebelement", "520": "Zahntriebelement",
"521": "Kettentriebelement", "521": "Kettentriebelement",
@@ -373,6 +446,7 @@
}, },
"TOS_Sicherungselement": { "TOS_Sicherungselement": {
"TOS-level": 3, "TOS-level": 3,
"_comment" : "54 - Maschinenelement -> Sicherungselement",
"children": { "children": {
"540": "Schraubensicherung", "540": "Schraubensicherung",
"541": "Wellen-/Bohrungssicherung", "541": "Wellen-/Bohrungssicherung",
@@ -382,6 +456,7 @@
}, },
"TOS_Bedienungselement": { "TOS_Bedienungselement": {
"TOS-level": 3, "TOS-level": 3,
"_comment" : "55 - Maschinenelement -> Bedienungselement",
"children": { "children": {
"550": "Griffe", "550": "Griffe",
"551": "Hebel", "551": "Hebel",
@@ -392,6 +467,7 @@
}, },
"TOS_Schoenenberger_Komponenten": { "TOS_Schoenenberger_Komponenten": {
"TOS-level": 2, "TOS-level": 2,
"_comment" : "6 - Schönenberger Komponenten",
"children": { "children": {
"60": "frei", "60": "frei",
"61": "frei", "61": "frei",
@@ -408,8 +484,9 @@
}, },
"TOS_Pneumatik": { "TOS_Pneumatik": {
"TOS-level": 2, "TOS-level": 2,
"_comment" : "7 - Pneumatik",
"children": { "children": {
"70": "Pneumatische Antriebe und Zylinder", "70": "Pneumatischer Antrieb und Zylinder",
"71": "Ventil", "71": "Ventil",
"72": "Sensoren und Leitungen", "72": "Sensoren und Leitungen",
"73": "Schlauch", "73": "Schlauch",
@@ -421,6 +498,7 @@
}, },
"TOS_Konfig": { "TOS_Konfig": {
"TOS-level": 2, "TOS-level": 2,
"_comment" : "8 - Konfiguration",
"children": { "children": {
"80": "Texte", "80": "Texte",
"81": "Band-Konfiguration", "81": "Band-Konfiguration",
+21
View File
@@ -7,8 +7,11 @@ Schwermetall
[Stahl] [Stahl]
1.0035 (S185) 1.0035 (S185)
1.0038 (S235JR) 1.0038 (S235JR)
1.0038+AR (S235JR+AR)
1.0038+CR (S235JR+CR)
1.0122 (S235JRC) 1.0122 (S235JRC)
1.0122+C (S235JRC+C) 1.0122+C (S235JRC+C)
1.0242+Z275-M-A-C (S250GD+Z275-M-A-C)
1.0330 (DC01) 1.0330 (DC01)
1.0401 (C15) 1.0401 (C15)
1.0501 (C35) 1.0501 (C35)
@@ -21,6 +24,7 @@ Schwermetall
1.0715+C (11SMn30+C) 1.0715+C (11SMn30+C)
1.0917 (DX51D+Z) 1.0917 (DX51D+Z)
1.1191 (C45E) 1.1191 (C45E)
1.1221 (C60E)
1.2842 (90MnCrV8) 1.2842 (90MnCrV8)
1.4035 (X45CrS13) 1.4035 (X45CrS13)
1.4301 (X5CrNi18-10) 1.4301 (X5CrNi18-10)
@@ -28,18 +32,22 @@ Schwermetall
1.4310 (X10CrNi18-8) 1.4310 (X10CrNi18-8)
1.5023 (38Si7) 1.5023 (38Si7)
1.7131 (16MnCr5) 1.7131 (16MnCr5)
1.7225 (42CrMo4)
siehe Hersteller siehe Hersteller
siehe Stückliste
[Aluminium] [Aluminium]
EN AW-1050A (3.0255) EN AW-1050A (3.0255)
EN AW-2007 (3.1645) EN AW-2007 (3.1645)
EN AW-2014-T3 (3.1255-T3) EN AW-2014-T3 (3.1255-T3)
EN AW-2014-T4 (3.1255-T4) EN AW-2014-T4 (3.1255-T4)
EN AW-5754 (3.3535)
EN AW-6060 (3.3206) EN AW-6060 (3.3206)
EN AW-6060-T66 (3.3206-T66) EN AW-6060-T66 (3.3206-T66)
EN AW-7075 (3.4365) EN AW-7075 (3.4365)
EN AW-6063-T66 EN AW-6063-T66
siehe Hersteller siehe Hersteller
siehe Stückliste
[Kunst-/ Verbundstoff] [Kunst-/ Verbundstoff]
ABS ABS
@@ -48,6 +56,7 @@ CR/SBR-A65
Hostaform 13031 MB1.5 Hostaform 13031 MB1.5
Irogran A87 Irogran A87
Murtfeldt "S" 1000 Murtfeldt "S" 1000
Murtfeldt Original "S" grün
PA PA
PA 2200 PA 2200
PA 2200 SLS PA 2200 SLS
@@ -57,32 +66,44 @@ PA 6 GF 30
PA 66 PA 66
PA 66 GF 25 PA 66 GF 25
PA 66 GF 30 PA 66 GF 30
PA 66 GF 50
PA GF 25 PA GF 25
PBT PBT
PC PC
PC GF 10
PE PE
PE-HD PE-HD
PE-LD PE-LD
PE-UHMW PE-UHMW
PE-UHMW antistatisch
POM POM
POM-C POM-C
POM-H POM-H
PP PP
PP-C PP-C
PP-H PP-H
PP SLS
PP T20
PTFE PTFE
PUR PUR
PUR - 95 Shore A
PUR D44 - 80 Shore A
PVC PVC
PVC-P (weich)
PVC-U PVC-U
siehe Hersteller siehe Hersteller
siehe Stückliste
TPU TPU
TPU - 95 Shore A
TPU - 98 Shore A TPU - 98 Shore A
[Schwermetall] [Schwermetall]
CC493K - GC (CuSn7Zn4Pb7 - C - GC)
CW459K (CuSn8P) CW459K (CuSn8P)
CW614N (CuZn39Pb3) CW614N (CuZn39Pb3)
CW708R (CuZn31Si) CW708R (CuZn31Si)
siehe Hersteller siehe Hersteller
siehe Stückliste
[Festigkeitsklasse] [Festigkeitsklasse]
010.9 010.9
+12 -3
View File
@@ -1,6 +1,15 @@
[Zielpfade] [Zielpfade]
\\ssg.local\freigaben\SIVAS_CAD_EDM\Migration\02_Bedarfspool Produktiv=\\ssg.local\freigaben\SIVAS_CAD_EDM\Migration\02_Bedarfspool
\\ssg.local\freigaben\SIVAS_CAD_EDM\Schulung\Migration\02_Bedarfspool Schulung=\\ssg.local\freigaben\SIVAS_CAD_EDM\Schulung\Migration\02_Bedarfspool
[3D-Modelle] [3D-Modelle]
\\ssg.local\freigaben\SIVAS_CAD_EDM\Migration\01_Rohdatenpool BaugruppeSchweissbaugruppe=\\ssg.local\freigaben\Abteilungen\Entwicklung\CAD\Standards\SolidEdge\Template\DIN Metric\baugruppe.asm
Kaufteil=\\ssg.local\freigaben\SIVAS_CAD_EDM\Migration\06_3D_Vorlagen\ET_mit_Volumen.par
Einzelteil=\\ssg.local\freigaben\SIVAS_CAD_EDM\Migration\06_3D_Vorlagen\ET_mit_Volumen.par
EinzelteilDefault=\\ssg.local\freigaben\SIVAS_CAD_EDM\Migration\01_Rohdatenpool\
# [3D-Modelle]
# BaugruppeSchweissbaugruppe=Baugruppe
# Kaufteil=Kaufteil
# Einzelteil=Einzelteil
# EinzelteilDefault=C:\Users\m.stangl\Documents\10-Develop\CreoMigrate\work\test
+20 -13
View File
@@ -1,20 +1,27 @@
[EinzelTextblöcke] [EinzelTextblöcke]
Version=ACHTUNG Index in Sivas mit Kleinbuchstaben. Nach Freigabe der Teilenummer den großen Index in SIVAS löschen und auf kleinen verlinken. Sobald die Revision höher als '{"Version"}' ist kann Information gelöscht werden. Kleinbuchstabe=ACHTUNG Kleinbuchstaben-Index in SIVAS. Nach Freigabe der Teilenummer in SIVAS den Großbuchstaben-Index löschen, alle Dokumente auf den Kleinbuchstaben-Index verlinken und den Kleinbuchstaben-Index erneut freigeben. Sobald die Revision höher als {aenderungsindex} ist kann diese Zusatzinformation aus RuleDesigner gelöscht werden.
Truemmer=ACHTUNG Trümmerbaugruppe. Nach einer Revision oder Bagatelländerung muss der Rüstcode in der Stücklisten bei allen Stücklistenpositionen manuell in "TR - Trümmerteile" geändert werden. Truemmer=ACHTUNG Trümmerbaugruppe. Nach einer Revision oder Bagatelländerung muss der Rüstcode in der SIVAS-Stückliste bei allen Stücklistenpositionen manuell in "TR - Trümmerteile" geändert werden.
Blacklist=ACHTUNG BG mit Beistellungen. Es wird keine Stückliste übergeben. Diese muss bei einer Änderung händisch angelegt und archiviert werden. Hierfür die Verantwortlichen für den Teilestamm informieren. BlacklistBG=ACHTUNG BG mit Beistellungen. Es wird keine Stückliste übergeben. Diese muss bei einer Änderung händisch angelegt und archiviert werden. Hierfür die Verantwortlichen für den Teilestamm informieren.
BlacklistHZ=ACHTUNG Bearbeitetes Halbzeug mit Beistellungen. Es wird keine Stückliste übergeben. Diese muss bei einer Änderung händisch angelegt und archiviert werden. Hierfür die Verantwortlichen für den Teilestamm informieren.
Werkstoffdiskrepanz=ACHTUNG Materialdiskrepanz. SIVAS-Material und/oder Zeichnungsmaterial / geliefertes Material unterschiedlich. Muss abgeklärt werden. Näheres siehe JIRA. Werkstoffdiskrepanz=ACHTUNG Materialdiskrepanz. SIVAS-Material und/oder Zeichnungsmaterial / geliefertes Material unterschiedlich. Muss abgeklärt werden. Näheres siehe JIRA.
Dispoinaktiv=ACHTUNG BG mit dispoinaktiven Stücklistenpositionen. Es wird keine Stückliste übergeben. Diese muss bei einer Änderung händisch angelegt und archiviert werden. Hierfür die Verantwortlichen für den Teilestamm informieren.
[ComboTextblöcke] [ComboTextblöcke]
VersionTruemmer=ACHTUNG Index in Sivas mit Kleinbuchstaben + Trümmerbaugruppe. Ausführliche Informationen zu erforderlichen Tätigkeiten / potentiellen Fehlern vgl. Konstruktionsrichtlinien KleinbuchstabeTruemmer=ACHTUNG Index in Sivas mit Kleinbuchstaben + Trümmerbaugruppe. Ausführliche Informationen zu erforderlichen Tätigkeiten / potentiellen Fehlern vgl. Konstruktionsrichtlinien
VersionBlacklist=ACHTUNG Index in Sivas mit Kleinbuchstaben + BG mit Beistellungen. Ausführliche Informationen zu erforderlichen Tätigkeiten / potentiellen Fehlern vgl. Konstruktionsrichtlinien KleinbuchstabeBlacklistBG=ACHTUNG Index in Sivas mit Kleinbuchstaben + BG mit Beistellungen. Ausführliche Informationen zu erforderlichen Tätigkeiten / potentiellen Fehlern vgl. Konstruktionsrichtlinien
VersionWerkstoffdiskrepanz=ACHTUNG Index in Sivas mit Kleinbuchstaben + Materialdiskrepanz. Ausführliche Informationen zu erforderlichen Tätigkeiten / potentiellen Fehlern vgl. Konstruktionsrichtlinien KleinbuchstabeWerkstoffdiskrepanz=ACHTUNG Index in Sivas mit Kleinbuchstaben + Materialdiskrepanz. Ausführliche Informationen zu erforderlichen Tätigkeiten / potentiellen Fehlern vgl. Konstruktionsrichtlinien
TruemmerBlacklist=ACHTUNG Trümmerbaugruppe + BG mit Beistellungen. Ausführliche Informationen zu erforderlichen Tätigkeiten / potentiellen Fehlern vgl. Konstruktionsrichtlinien KleinbuchstabeDispoinaktiv=ACHTUNG Index in Sivas mit Kleinbuchstaben + BG mit Dispoinaktiven Stücklistenpositionen. Ausführliche Informationen zu erforderlichen Tätigkeiten / potentiellen Fehlern vgl. Konstruktionsrichtlinien
TruemmerBlacklistBG=ACHTUNG Trümmerbaugruppe + BG mit Beistellungen. Ausführliche Informationen zu erforderlichen Tätigkeiten / potentiellen Fehlern vgl. Konstruktionsrichtlinien
TruemmerWerkstoffdiskrepanz=ACHTUNG Trümmerbaugruppe + Materialdiskrepanz. Ausführliche Informationen zu erforderlichen Tätigkeiten / potentiellen Fehlern vgl. Konstruktionsrichtlinien TruemmerWerkstoffdiskrepanz=ACHTUNG Trümmerbaugruppe + Materialdiskrepanz. Ausführliche Informationen zu erforderlichen Tätigkeiten / potentiellen Fehlern vgl. Konstruktionsrichtlinien
VersionTruemmerBlacklist=ACHTUNG Index in Sivas mit Kleinbuchstaben + Trümmerbaugruppe + BG mit Beistellungen. Ausführliche Informationen zu erforderlichen Tätigkeiten / potentiellen Fehlern vgl. Konstruktionsrichtlinien TruemmerDispoinaktiv=ACHTUNG Trümmerbaugruppe + BG mit dispoinaktiven Stücklistenpositionen. Ausführliche Informationen zu erforderlichen Tätigkeiten / potentiellen Fehlern vgl. Konstruktionsrichtlinien
KleinbuchstabeTruemmerBlacklist=ACHTUNG Index in Sivas mit Kleinbuchstaben + Trümmerbaugruppe + BG mit Beistellungen. Ausführliche Informationen zu erforderlichen Tätigkeiten / potentiellen Fehlern vgl. Konstruktionsrichtlinien
KleinbuchstabeTruemmerDispoinaktiv=ACHTUNG Index in Sivas mit Kleinbuchstaben + Trümmerbaugruppe + BG mit dispoinaktiven Stücklistenpositionen. Ausführliche Informationen zu erforderlichen Tätigkeiten / potentiellen Fehlern vgl. Konstruktionsrichtlinien
BlacklistHZDispoinaktiv=ACHTUNG Bearbeitetes Halbzeug mit beigestellten und dispoinaktiven Stücklistenpositionen. Es wird keine Stückliste übergeben. Diese muss bei einer Änderung händisch angelegt und archiviert werden. Hierfür die Verantwortlichen für den Teilestamm informieren.
BlacklistBGDispoinaktiv=ACHTUNG BG mit beigestellten und dispoinaktiven Stücklistenpositionen. Es wird keine Stückliste übergeben. Diese muss bei einer Änderung händisch angelegt und archiviert werden. Hierfür die Verantwortlichen für den Teilestamm informieren.
;Nachfolgende Kombinationen können nicht auftreten: ;Nachfolgende Kombinationen können nicht auftreten:
;- BlacklistWerkstoffdiskrepanz ;- BlacklistBGWerkstoffdiskrepanz
;- VersionTruemmerWerkstoffdiskrepanz ;- KleinbuchstabeTruemmerWerkstoffdiskrepanz
;- VersionBlacklistWerkstoffdiskrepanz ;- KleinbuchstabeBlacklistBGWerkstoffdiskrepanz
;- TruemmerBlacklistWerkstoffdiskrepanz= ;- TruemmerBlacklistBGWerkstoffdiskrepanz
;- VersionTruemmerBlacklistWerkstoffdiskrepanz= ;- KleinbuchstabeTruemmerBlacklistBGWerkstoffdiskrepanz
+10
View File
@@ -0,0 +1,10 @@
[Fenster]
#Büro-Auflösung (hochformat)
CanvasBreite=1080
CanvasHoehe=1490
Dimension=1080x1490
# Homeoffice Auflösung (querformat)
# CanvasBreite=1000
# CanvasHoehe=1350
# Dimension=1100x1400
+4
View File
@@ -0,0 +1,4 @@
[Fenster]
CanvasBreite=950
CanvasHoehe=1450
Dimension=970x900
+7 -11
View File
@@ -44,15 +44,15 @@
inkscape:pageopacity="0" inkscape:pageopacity="0"
inkscape:pagecheckerboard="0" inkscape:pagecheckerboard="0"
inkscape:deskcolor="#646464" inkscape:deskcolor="#646464"
inkscape:zoom="0.5" inkscape:zoom="0.70710678"
inkscape:cx="178" inkscape:cx="499.21739"
inkscape:cy="769" inkscape:cy="1096.7226"
inkscape:window-width="2560" inkscape:window-width="1920"
inkscape:window-height="1377" inkscape:window-height="1017"
inkscape:window-x="-8" inkscape:window-x="-8"
inkscape:window-y="-8" inkscape:window-y="108"
inkscape:window-maximized="1" inkscape:window-maximized="1"
inkscape:current-layer="g107" inkscape:current-layer="g1"
showgrid="false" showgrid="false"
showguides="true"><inkscape:page showguides="true"><inkscape:page
x="0" x="0"
@@ -1921,10 +1921,6 @@
id="path207" id="path207"
d="m 1677.5192,1265.858 0.061,21.9234 -232.6023,0.3586 v -22.282 z" d="m 1677.5192,1265.858 0.061,21.9234 -232.6023,0.3586 v -22.282 z"
style="fill:none;stroke:#afafaf;stroke-width:1.50001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1" style="fill:none;stroke:#afafaf;stroke-width:1.50001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
sodipodi:nodetypes="ccccc" /><path
id="path208"
d="m 1941.7978,1265.858 0.061,21.9234 -232.6023,0.3586 v -21.9233 z"
style="fill:none;stroke:#afafaf;stroke-width:1.50001;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:10;stroke-dasharray:none;stroke-opacity:1"
sodipodi:nodetypes="ccccc" /></g><g sodipodi:nodetypes="ccccc" /></g><g
id="g44" id="g44"
transform="translate(-0.03690938,1.4420048)"><text transform="translate(-0.03690938,1.4420048)"><text

Before

Width:  |  Height:  |  Size: 164 KiB

After

Width:  |  Height:  |  Size: 164 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.1 KiB

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

+120 -91
View File
@@ -8,9 +8,9 @@ Beim Doppelklick auf eine bereits migrierte Teilenummer dürfen die Formularfeld
**Allgemeine Hinweise:** **Allgemeine Hinweise:**
1. Für jedes der nachfolgend aufgelisteten Feldnamen (z.B. "Teilenummer") soll ein Label-Widget in der 1. Spalte "Feld" der GUI erstellt werden. Labeltext ist jeweils der Feldname. Ausnahme ist das Feld "Baugruppennummer", bei dem das Label und ein Entry-Feld oberhalb des Treeviews liegen. 1. Für jedes der nachfolgend aufgelisteten Feldnamen (z.B. "Teilenummer") soll ein Label-Widget in der 1. Spalte "Feld" der GUI erstellt werden. Labeltext ist jeweils der Feldname. Ausnahme ist das Feld "Baugruppennummer", bei dem das Label und ein Entry-Feld oberhalb des Treeviews liegen.
2. Die eingetragenen Feldwerte sollen in einer json-Datei gespeichert werden. Wird eine Teilenummer geöffnet/bearbeitet, für die bereits eine json-Datei exisitert, müssen die Felder mit den Werten aus dieser json-Datei befüllt werden. Nur beim erstmaligen Öffnen/Bearbeiten einer Teilenummer dürfen Felder geleert oder auf den Defaultwert umgestellt werden. Art und Umfang dieser initialen Feldanpassungen wird in den nachfolgenden Feldspezifikationen näher beschrieben. 2. Die eingetragenen Feldwerte sollen in einer json-Datei gespeichert werden. Wird eine Teilenummer geöffnet/bearbeitet, für die bereits eine json-Datei exisitert, müssen die Felder mit den Werten aus dieser json-Datei befüllt werden. Nur beim erstmaligen Öffnen/Bearbeiten einer Teilenummer dürfen Felder geleert oder auf den Defaultwert umgestellt werden. Art und Umfang dieser initialen Feldanpassungen wird in den nachfolgenden Feldspezifikationen näher beschrieben.
3. Defaultwert bedeutet, dass beim Bearbeiten einer **neuen** Teilenummer, die noch keine json-Datei besitzt, ein bestimmter, voreingestellter Wert eingetragen / vorausgewählt ist 3. Defaultwert bedeutet in den nachfolgenden Feldspezifikationen, dass beim Doppelklick auf eine Teilenummer im Treeview, die zum ersten mal bearbeitet wird (also noch keine json-Speicherdatei im [work-Ordner](../work/) exisitiert (siehe oben Punkt 2)), ein bestimmter, voreingestellter Wert in das Feld eingetragen / vorausgewählt wird
4. "state" beschreibt in den nachfolgenden Feldspezifikationen den Parameter "state" des tk-Widgets. Dieser Parameter definiert, in welchem Umfang ein User mit dem Widget interagieren kann 4. "state" beschreibt in den nachfolgenden Feldspezifikationen den Parameter "state" des tk-Widgets. Dieser Parameter definiert, in welchem Umfang ein User mit dem Widget interagieren kann. Beispiel: bei einem Eingabefeld (Entry) sorgt der state "readonly" dafür, dass kein Text in das Eingabefeld eingetragen, aber der Text daraus kopiert werden kann. Hingegen kann beim state "disabled" weder Text eingetragen, noch kopiert werden. Wird überhaupt kein state vorgegeben, kann der User wiederum sowohl Text eingeben, als auch Text kopieren.
5. "from_siv.csv" beschreibt nachfolgend die CSV-Datei, welche die Teilestamminformationen zu einer Teilenummer enthält. Die CSV wird durch den Sivas-internen Prozess "ExcelUeb" von Hr. Jakob erzeugt (siehe auch [get_sivas_teilestamm.py](../lib/get_sivas_teilestamm.py)) 5. "from_siv.csv" beschreibt nachfolgend die CSV-Datei, welche die Teilestamminformationen zu einer Teilenummer enthält. Die CSV wird durch den Sivas-internen Prozess "ExcelUeb" von Hr. Jakob erzeugt (der Aufruf des Prozesses erfolgt im Pythonprogramm [get_sivas_teilestamm.py](../lib/get_sivas_teilestamm.py))
--- ---
@@ -41,7 +41,8 @@ Besitzt die eingetragenen Teilenummer keine Stückliste, soll im Treeview nur di
>**Pflichtfeld:** Ja, immer >**Pflichtfeld:** Ja, immer
--- ---
#### **Spalte 2: SIVAS-Werte** #### **Spalte 2: SIVAS-Werte**
>**Widget-Typ:** Entry >**Widget:**
>**Typ:** Entry
>**state:** readonly >**state:** readonly
>**Wert:** Aus Spalte "Teilenummer" in "from_siv.csv" >**Wert:** Aus Spalte "Teilenummer" in "from_siv.csv"
@@ -77,7 +78,8 @@ Wird zur Definierung des Wertes in der Spalte "New Path" benötigt, siehe [Impfd
>**Pflichtfeld:** Ja, immer >**Pflichtfeld:** Ja, immer
--- ---
#### **Spalte 3: Überschriebene Werte** #### **Spalte 3: Überschriebene Werte**
>**Widget-Typ:** ComboBox >**Widget:**
>**Typ:** ComboBox
>**Werte:** Sektion "Kategorien" in [Allgemein.cfg](../cfg/Allgemein.cfg) >**Werte:** Sektion "Kategorien" in [Allgemein.cfg](../cfg/Allgemein.cfg)
>**Defaultwert:** Leer -> Kategoriefestlegung kann nicht automatisch erfolgen >**Defaultwert:** Leer -> Kategoriefestlegung kann nicht automatisch erfolgen
>**state:** readonly >**state:** readonly
@@ -437,26 +439,27 @@ Der Wert aus der Spalte "HzOhneSaegeliste" in "from_siv.csv" muss in gemappter /
--- ---
#### **Spalte 3: Überschriebene Werte** #### **Spalte 3: Überschriebene Werte**
>**Widget-Typ:** ComboBox >**Widget:**
>**Typ:** ComboBox
>**Defaultwert:** "" (leer) >**Defaultwert:** "" (leer)
**Nachfolgende Logik definiert:** **Nachfolgende Logik definiert:**
- state der ComboBox je nach Situation (readonly / disabled) - state der ComboBox je nach Situation (readonly / disabled)
- Dropdownwerte (Quelle, wo die Dropdownwerte zu finden sind, bzw. direkt die Werte) - Dropdownwerte (Quelle, wo die Dropdownwerte zu finden sind, bzw. direkt die Werte)
-
IF PDM-Kategorie == "Baugruppe": IF PDM-Kategorie == "Baugruppe":
Dropdownwerte = None (keine Werte) Dropdownwerte = None (keine Werte)
state = disabled state = disabled
ELSE IF PDM-Kategorie != "Baugruppe": ELSE IF PDM-Kategorie != "Baugruppe":
IF Rüstcode == "HZS Halbzeuge Sägeteile": IF Rüstcode == "HZS Halbzeuge Sägeteile":
Dropdownwerte = Sektion "HalbzeugOhneSaegeliste" aus Allgemein.cfg Dropdownwerte = Sektion "HalbzeugOhneSaegeliste" aus Allgemein.cfg
state = readonly state = readonly
ELSE IF Rüstcode == "SRC Standard Rüstcode": ELSE IF Rüstcode == "SRC Standard Rüstcode":
Dropdownwerte = None (keine Werte) Dropdownwerte = None (keine Werte)
state = disabled state = disabled
--- ---
#### **Migration** #### **Migration**
@@ -479,7 +482,8 @@ Der Wert aus der Spalte "HzOhneSaegeliste" in "from_siv.csv" muss in gemappter /
--- ---
#### **Spalte 3: Überschriebene Werte** #### **Spalte 3: Überschriebene Werte**
>**Widget-Typ:** ComboBox >**Widget:**
>**Typ:** ComboBox
>**state:** readonly >**state:** readonly
**Nachfolgende Logik definiert:** **Nachfolgende Logik definiert:**
@@ -541,7 +545,8 @@ Es muss geprüft werden, ob ein zulässiger Rüstcode eingetragen ist, siehe [Fe
--- ---
#### **Spalte 3: Überschriebene Werte** #### **Spalte 3: Überschriebene Werte**
>**Widget-Typ:** ComboBox >**Widget:**
>**Typ:** ComboBox
**Nachfolgende Logik definiert:** **Nachfolgende Logik definiert:**
- Dropdownwerte (Quelle, wo die Dropdownwerte zu finden sind, bzw. direkt die Werte) - Dropdownwerte (Quelle, wo die Dropdownwerte zu finden sind, bzw. direkt die Werte)
@@ -599,7 +604,8 @@ Es muss geprüft werden, ob ein zulässiger Rüstcode eingetragen ist, siehe [Fe
--- ---
#### **Spalte 3: Überschriebene Werte** #### **Spalte 3: Überschriebene Werte**
>**Widget-Typ:** ComboBox >**Widget:**
>**Typ:** ComboBox
**Nachfolgende Logik definiert:** **Nachfolgende Logik definiert:**
- Dropdownwerte (Quelle, wo die Dropdownwerte zu finden sind, bzw. direkt die Werte) - Dropdownwerte (Quelle, wo die Dropdownwerte zu finden sind, bzw. direkt die Werte)
@@ -690,7 +696,8 @@ Es muss geprüft werden, ob ein zulässiger Rüstcode eingetragen ist, siehe [Fe
--- ---
#### **Spalte 3: Überschriebene Werte** #### **Spalte 3: Überschriebene Werte**
>**Widget-Typ:** ComboBox >**Widget:**
>**Typ:** ComboBox
**Nachfolgende Logik definiert:** **Nachfolgende Logik definiert:**
- Dropdownwerte (Quelle, wo die Dropdownwerte zu finden sind, bzw. direkt die Werte) - Dropdownwerte (Quelle, wo die Dropdownwerte zu finden sind, bzw. direkt die Werte)
@@ -746,7 +753,8 @@ Es muss geprüft werden, ob ein zulässiger Rüstcode eingetragen ist, siehe [Fe
--- ---
#### **Spalte 3: Überschriebene Werte** #### **Spalte 3: Überschriebene Werte**
>**Widget-Typ:** ComboBox >**Widget:**
>**Typ:** ComboBox
**Nachfolgende Logik definiert:** **Nachfolgende Logik definiert:**
- Dropdownwerte (Quelle, wo die Dropdownwerte zu finden sind, bzw. direkt die Werte) - Dropdownwerte (Quelle, wo die Dropdownwerte zu finden sind, bzw. direkt die Werte)
@@ -808,7 +816,8 @@ Der Wert "Eigenbaugruppe" aus der Spalte "Beschaffungsart" in "from_siv.csv" mus
--- ---
#### **Spalte 3: Überschriebene Werte** #### **Spalte 3: Überschriebene Werte**
>**Widget-Typ:** ComboBox >**Widget:**
>**Typ:** ComboBox
**Nachfolgende Logik definiert:** **Nachfolgende Logik definiert:**
- Dropdownwerte (Quelle, wo die Dropdownwerte zu finden sind, bzw. direkt die Werte) - Dropdownwerte (Quelle, wo die Dropdownwerte zu finden sind, bzw. direkt die Werte)
@@ -873,7 +882,8 @@ Der Wert "Eigenbaugruppe" aus der Spalte "Beschaffungsart" in "from_siv.csv" mus
--- ---
#### **Spalte 3: Überschriebene Werte** #### **Spalte 3: Überschriebene Werte**
>**Widget-Typ:** ComboBox >**Widget:**
>**Typ:** ComboBox
>**Defaultwert:** Keiner (leer) >**Defaultwert:** Keiner (leer)
>**Read only:** Ja >**Read only:** Ja
@@ -1190,7 +1200,8 @@ Der Text vor dem Herstellernamen (besteht aus Herstellernummer + Zeichenkette "
--- ---
#### **Spalte 3: Überschriebene Werte** #### **Spalte 3: Überschriebene Werte**
>**Widget-Typ:** Entry >**Widget:**
>**Typ:** Entry
>**Defaultwert:** "" (keiner) >**Defaultwert:** "" (keiner)
**Nachfolgende Logik definiert:** **Nachfolgende Logik definiert:**
@@ -1353,7 +1364,8 @@ Vor der Erstellung der Impfdatei muss geprüft werden, ob ein gültiger Werkstof
--- ---
#### **Spalte 3: Überschriebene Werte** #### **Spalte 3: Überschriebene Werte**
>**Widget-Typ:** ComboBox >**Widget:**
>**Typ:** ComboBox
- state der ComboBox je nach Situation (readonly / disabled) - state der ComboBox je nach Situation (readonly / disabled)
@@ -1661,22 +1673,13 @@ Erfolgt eine Wertänderung in der ComboBox des Feldes [Werkstofftyp](#werkstofft
>**Wert:** Aus Spalte "Version" in "from_siv.csv" >**Wert:** Aus Spalte "Version" in "from_siv.csv"
--- In diesem Feld soll informativ der Wert aus dem SIVAS-Feld "Version" dargestellt werden.
Der Feldwert wird für die Bestimmung des [Freigabevermerks](#freigabevermerk) benötigt
#### **Spalte 3: Überschriebene Werte**
>**Widget:**
>**Typ:** Entry
#### **Migration**
>**Spaltenname Impfdatei:** Wird nicht in Impfdatei berücksichtigt
- Wird für die Bestimmung des [Freigabevermerks](#freigabevermerk) benötigt
--- ---
### Änderungsindex ### Änderungsindex
>**Pflichtfeld:** Nein >**Pflichtfeld:** Ja
--- ---
#### **Spalte 2: SIVAS-Werte** #### **Spalte 2: SIVAS-Werte**
>**Widget:** >**Widget:**
@@ -1687,14 +1690,27 @@ Erfolgt eine Wertänderung in der ComboBox des Feldes [Werkstofftyp](#werkstofft
--- ---
#### **Spalte 3: Überschriebene Werte** #### **Spalte 3: Überschriebene Werte**
>**Widget-Typ:** Entry >**Widget:**
>**Typ:** Entry
>**state:** disabled
**Logik, die steuert, welcher Defaultwert gilt:**
IF Wert in Spalte "AktuellerIndex" in "from_siv.csv" == "" (leer):
Defaultwert = "A"
ELSE IF Wert in Spalte "AktuellerIndex" in "from_siv.csv" == Kleinbuchstabe:
Defaultwert = Großbuchstabe (des Buchstabens, der in Spalte "AktuellerIndex" steht)
Beispiel für diesen Fall:
In Spalte "AktuellerIndex" steht der Kleinbuchstabe "b". Dann soll in das Entry-Feld der Großbuchstabe "B" eingetragen werden
ELSE:
Defaultwert = "" (leer)
#### **Migration** #### **Migration**
>**Spaltenname Impfdatei:** StartRevision >**Spaltenname Impfdatei:** StartRevision
Liegt kein Änderungsindex vor, muss "A" in die Impfdatei eingetragen werden (siehe [Impfdateierstellung](#tätigkeiten-im-rahmen-der-impfdateierstellung))
--- ---
### Änderungstext ### Änderungstext
@@ -1707,18 +1723,19 @@ Liegt kein Änderungsindex vor, muss "A" in die Impfdatei eingetragen werden (si
>**Wert:** Aus Spalte "Aenderungstext" in "from_siv.csv" >**Wert:** Aus Spalte "Aenderungstext" in "from_siv.csv"
**Aufgaben beim Einlesen des Wertes aus "from_siv.csv":** **Aufgaben beim Einlesen des Wertes aus "from_siv.csv":**
- Semikolon (einschließlich vor- und nachgesetztem Leerzeichen) sollen durch ein Slash mit vor- und nachgesetztem Leerzeichen (" / ") ersetzt werden. Beispiel: - Semikolon (einschließlich gegebenenfalls vor- und nachgesetztem Leerzeichen) sollen durch ein Slash mit vor- und nachgesetztem Leerzeichen (" / ") ersetzt werden. Beispiel:
- Änderungstext in "from_siv.csv": "Gewindebohrung auf M5 vergrößert (war M4); Fasen entfernt" - Änderungstext in "from_siv.csv": "Gewindebohrung auf M5 vergrößert (war M4); Fasen entfernt"
- Änderungstext nach dem Einlesen: "Gewindebohrung auf M5 vergrößert (war M4) / Fasen entfernt" - Änderungstext nach dem Einlesen: "Gewindebohrung auf M5 vergrößert (war M4) / Fasen entfernt"
- Wenn die Spalte "Aenderungstext" in "from_siv.csv" einen Wert enthält, soll der Textbaustein "(von {Wert aus Spalte "Indexerfasser in 'from_siv.csv'})" angehängt werden, Beispiel: - Wenn die Spalte "Aenderungstext" in "from_siv.csv" einen Wert enthält, soll der Textbaustein " (von {Wert aus Spalte "Indexerfasser" in 'from_siv.csv'})" angehängt werden, Beispiel:
- Änderungstext in "from_siv.csv": "Biegeradius auf R5 vergrößert (war R4)" - Änderungstext in "from_siv.csv": "Biegeradius auf R5 vergrößert (war R4)"
- Änderungstext nach dem Einlesen: "Biegeradius auf R5 vergrößert (war R4) (von M.SCHNEIDER)" - Änderungstext nach dem Einlesen: "Biegeradius auf R5 vergrößert (war R4) (von M.SCHNEIDER)"
--- ---
#### **Spalte 3: Überschriebene Werte** #### **Spalte 3: Überschriebene Werte**
>**Widget-Typ:** Text (mehrzeilig) >**Widget:**
>**Typ:** Text (mehrzeilig)
>**Zeichenbegrenzung:** 400 >**Zeichenbegrenzung:** 400
**Bestimmung der Zeichenbegrenzung:** **Bestimmung der Zeichenbegrenzung:**
@@ -1726,23 +1743,23 @@ Wenn die Länge des Änderungstextes in der Spalte "SIVAS-Werte" die Zeichengren
**Logik, die steuert, welcher Defaultwert gilt:** **Logik, die steuert, welcher Defaultwert gilt:**
IF Wert aus Spalte "Aenderungstext" in "from_siv.csv" == "": IF Wert aus Spalte "Aenderungstext" in "from_siv.csv" == "" (leer):
IF PDM-Kategorie == "Kaufteil": IF Wert aus Spalte "AktuellerIndex" in "from_siv.csv" == "" (leer):
Defaultwert = "Erstanlage" Defaultwert = "Erstanlage"
ELSE: ELSE:
Defaultwert = "Erstanlage (von {Indexerfasser})" Defaultwert = "Erstanlage (von {Wert aus Spalte "Indexerfasser" in "from_siv.csv"})"
ELSE: ELSE:
Defaultwert = "" Defaultwert = "" (leer)
--- ---
#### **Migration** #### **Migration**
>**Spaltenname in Impfdatei:** Änderungsbeschreibung >**Spaltenname in Impfdatei:** Änderungsbeschreibung
Es muss vor Erstellung der Impfdatei eine Längenprüfung durchgeführt werden, siehe [Tätigkeiten vor Erstellung der Impfdatei](#tätigkeiten-vor-erstellung-der-impfdatei) Es muss vor Erstellung der Impfdatei eine Längenprüfung durchgeführt werden, siehe [Feldprüfung Änderungstext](#änderungstext)
--- ---
@@ -1756,43 +1773,44 @@ Es muss vor Erstellung der Impfdatei eine Längenprüfung durchgeführt werden,
>**Wert:** Aus Spalte "Freigabevermerk" in "from_siv.csv" >**Wert:** Aus Spalte "Freigabevermerk" in "from_siv.csv"
**Aufgaben beim Einlesen des Wertes aus "from_siv.csv":** **Aufgaben beim Einlesen des Wertes aus "from_siv.csv":**
- Semikolon (einschließlich vor- und nachgesetztem Leerzeichen) sollen durch ein Slash mit vor- und nachgesetztem Leerzeichen (" / ") ersetzt werden. Beispiel: - Semikolon (einschließlich gegebenenfalls vor- und nachgesetztem Leerzeichen) sollen durch ein Slash mit vor- und nachgesetztem Leerzeichen (" / ") ersetzt werden. Beispiel:
- Freigabevermerk in "from_siv.csv": "Verringerte Rissgefahr durch größeren Biegeradius; Kostenreduktion durch geringere Blechstärke" - Freigabevermerk in "from_siv.csv": "Verringerte Rissgefahr durch größeren Biegeradius; Kostenreduktion durch geringere Blechstärke"
- Freigabevermerk nach dem Einlesen: "Verringerte Rissgefahr durch größeren Biegeradius / Kostenreduktion durch geringere Blechstärke" - Freigabevermerk nach dem Einlesen: "Verringerte Rissgefahr durch größeren Biegeradius / Kostenreduktion durch geringere Blechstärke"
--- ---
#### **Spalte 3: Überschriebene Werte** #### **Spalte 3: Überschriebene Werte**
>**Widget-Typ:** Text (mehrzeilig) >**Widget:**
>**Typ:** Text (mehrzeilig)
>**Zeichenbegrenzung:** 400 >**Zeichenbegrenzung:** 400
**Bestimmung der Zeichenbegrenzung:** **Bestimmung der Zeichenbegrenzung:**
Wie beim Feld [Änderungstext](#änderungstext) Wie beim Feld [Änderungstext](#aenderungstext)
**Logik, die steuert, welcher Defaultwert gilt:** **Logik, die steuert, welcher Defaultwert gilt:**
IF Wert aus Spalte "Freigabevermerk" in "from_siv.csv" == "": IF Wert aus Spalte "Freigabevermerk" in "from_siv.csv" == "":
IF PDM-Kategorie == "Kaufteil": IF PDM-Kategorie == "Kaufteil":
Defaultwert = "" Defaultwert = "" (leer)
ELSE: ELSE:
IF Wert aus Spalte "Version" in "from_siv.csv" == 6 aufeinanderfolgende Zahlen: IF Wert aus Spalte "Version" in "from_siv.csv" == genau 6 aufeinanderfolgende Zahlen:
Freigabevermerk = "Anpassung an neues Indexsystem, Zeichnung mit Versionsnummer {Wert aus Feld 'Version'} weiterhin gültig" Freigabevermerk = "Anpassung an neues Indexsystem, Zeichnung mit Versionsnummer {Wert aus Spalte 'Version' in "from_siv.csv"} weiterhin gültig"
ELSE: ELSE:
Defaultwert = "" Defaultwert = "" (leer)
ELSE: ELSE:
Defaultwert = "" Defaultwert = "" (leer)
--- ---
#### **Migration** #### **Migration**
>**Spaltenname in Impfdatei:** Freigabevermerk >**Spaltenname in Impfdatei:** Freigabevermerk
Es muss vor Erstellung der Impfdatei eine Längenprüfung durchgeführt werden, siehe [Tätigkeiten vor Erstellung der Impfdatei](#tätigkeiten-vor-erstellung-der-impfdatei) Es muss vor Erstellung der Impfdatei eine Längenprüfung durchgeführt werden, siehe [Feldprüfung Freigabevermerk](#freigabevermerk-1)
--- ---
@@ -1802,45 +1820,45 @@ Es muss vor Erstellung der Impfdatei eine Längenprüfung durchgeführt werden,
>**Widget:** >**Widget:**
>**Typ:** Text (mehrzeilig) >**Typ:** Text (mehrzeilig)
>**Zeichenbegrenzung:** 400 >**Zeichenbegrenzung:** 400
>**disabled:** Ja >**state:** readonly
**Logik, die steuert, welche vordefinierten Textblöcke je nach Situation in das Textfeld eingetragen werden sollen:** **Logik, die steuert, welcher vordefinierte Textblock je nach Situation in das Textfeld eingetragen werden soll:**
Hinweis: - Die nachfolgend aufgeführten Sektionen "EinzelTextblöcke" und "ComboTextblöcke" sind in der cfg-Datei [Zusatzinformationen.cfg](../cfg/Zusatzinformationen.cfg) enthalten.
Die nachfolgend aufgeführten Sektionen "EinzelTextblöcke" und "ComboTextblöcke" sind in der cfg-Datei [Zusatzinformationen.cfg](../cfg/Zusatzinformationen.cfg) enthalten. - Wenn in den nachfolgenden aufgelisteten Fällen der Fall "Text = Sektion "EinzelTextblöcke" -> Key "Kleinbuchstabe" gilt, muss der Text "{"Änderungsindex"}", der sich innerhalb des zutreffenden Textblockes in [Zusatzinformationen.cfg](../cfg/Zusatzinformationen.cfg) befindet, durch den Wert aus "self.aenderungsindex_neu" ersetzt werden (also den Wert aus dem Feld [Änderungsindex](#änderungsindex) in der GUI-Spalte "Überschrieberne Werte")
IF Version == Kleinbuchstabe: IF Änderungsindex == Kleinbuchstabe:
IF Trümmer == True OR Rüstcode == "": IF Trümmer == True OR Rüstcode == "":
Text = Sektion "ComboTextblöcke" -> Key "VersionTruemmer" Text = Sektion "ComboTextblöcke" -> Key "KleinbuchstabeTruemmer"
IF Teilenummer in Blacklist: IF Teilenummer in Blacklist:
Text = Sektion "ComboTextblöcke" -> Key "VersionTruemmerBlacklist" Text = Sektion "ComboTextblöcke" -> Key "KleinbuchstabeTruemmerBlacklist"
ELSE IF Teilenummer in Blacklist: ELSE IF Teilenummer in Blacklist:
Text = Sektion "ComboTextblöcke" -> Key "VersionBlacklist" Text = Sektion "ComboTextblöcke" -> Key "KleinbuchstabeBlacklist"
ELSE IF Werkstoffdiskrepanz == True: ELSE IF Werkstoffdiskrepanz == True:
Text = Sektion "ComboTextblöcke" -> Key "VersionWerkstoffdiskrepanz" Text = Sektion "ComboTextblöcke" -> Key "KleinbuchstabeWerkstoffdiskrepanz"
ELSE: ELSE:
Text = Sektion "EinzelTextblöcke" -> Key "Version" Text = Sektion "EinzelTextblöcke" -> Key "Kleinbuchstabe"
ELSE IF Trümmer == True OR "Rüstcode" == "": ELSE IF Trümmer == True OR "Rüstcode" == "":
IF Teilenummer in Blacklist: IF Teilenummer in Blacklist:
Text = Sektion "ComboTextblöcke" -> Key "TruemmerBlacklist" Text = Sektion "ComboTextblöcke" -> Key "TruemmerBlacklist"
ELSE IF Werkstoffdiskrepanz == True: ELSE IF Werkstoffdiskrepanz == True:
Text = Sektion "ComboTextblöcke" -> Key "TruemmerWerkstoffdiskrepanz" Text = Sektion "ComboTextblöcke" -> Key "TruemmerWerkstoffdiskrepanz"
ELSE: ELSE:
Text = Sektion "EinzelTextblöcke" -> Key "Truemmer" Text = Sektion "EinzelTextblöcke" -> Key "Truemmer"
--- ---
#### **Migration** #### **Migration**
>**Spaltenname Impfdatei:** keine eigene Spalte -> Wird zur Definierung des Wertes in der Spalte "ZusaetzlicheInformationen" benötigt, siehe [Impfdateierstellung](#tätigkeiten-im-rahmen-der-impfdateierstellung) >**Spaltenname Impfdatei:** keine eigene Spalte -> Wird zur Definierung des Wertes in der Spalte "ZusaetzlicheInformationen" benötigt, siehe [Impfdateierstellung - Zusätzliche Informationen](#zusaetzlicheinformationen)
### Benutzerdefinierte Zusatzinformationen ### Benutzerdefinierte Zusatzinformationen
@@ -1848,18 +1866,19 @@ Die nachfolgend aufgeführten Sektionen "EinzelTextblöcke" und "ComboTextblöck
>**Widget:** >**Widget:**
>**Typ:** Text (mehrzeilig) >**Typ:** Text (mehrzeilig)
>**disabled:** Nein >**state:** keiner
**Bestimmung der Zeichenbegrenzung:** **Bestimmung der Zeichenbegrenzung:**
Die Zeichenbegrenzung berechnet sich wie folgt: Die Zeichenbegrenzung berechnet sich wie folgt:
Zeichenbegrenzung = 400 - Aktuelle Anzahl an Zeichen im Textfeld [Automatische Zusatzinformationen](#automatische-zusatzinformationen) Zeichenbegrenzung = 400 - Aktuelle Anzahl an Zeichen im Textfeld [Automatische Zusatzinformationen](#automatische-zusatzinformationen)
Sobald die Zeichenbegrenzung erreicht ist soll der User keine weiteren Zeichen eintippen können, bzw. wenn der User weitere Zeichen eintippt, sollen diese nicht mehr dargestellt werden.
--- ---
#### **Migration** #### **Migration**
>**Spaltenname Impfdatei:** keine eigene Spalte -> Wird zur Definierung des Wertes in der Spalte "ZusaetzlicheInformationen" benötigt, siehe [Impfdateierstellung](#tätigkeiten-im-rahmen-der-impfdateierstellung) >**Spaltenname Impfdatei:** keine eigene Spalte -> Wird zur Definierung des Wertes in der Spalte "ZusaetzlicheInformationen" benötigt, siehe [Impfdateierstellung - Zusätzliche Informationen](#zusaetzlicheinformationen)
## Button Migrieren ## Button Migrieren
@@ -1878,7 +1897,7 @@ Zeichenbegrenzung = 400 - Aktuelle Anzahl an Zeichen im Textfeld [Automatische Z
#### Allgemeine Prüfungen: #### Allgemeine Prüfungen:
- Solange nicht alle Pflichtfelder einen Wert aufweisen, muss beim Klick auf den Button "Migrieren" eine ERROR-Messagebox erscheinen, in der alle Pflichtfelder aufgelistet sind, die keinen Wert aufweisen - Solange nicht alle Pflichtfelder einen Wert aufweisen, muss beim Klick auf den Button "Migrieren" eine ERROR-Messagebox erscheinen, in der alle Pflichtfelder aufgelistet sind, die keinen Wert aufweisen
- Es muss bei allen Feldern geprüft werden, ob sie ein unzulässiges Zeichen enthalten. Die Zeichen sind in der ini-Datei [ERP_Item.ini](\\ruledesigner\RDF_Daten\Konfigurator\CustomVaulting\ERP_Item.ini) in Sektion "Settings" unter dem Key "InvalidCharacters" aufgelistet: - Es muss bei allen Feldern (unabhängig davon, ob es sich um ein Pflichtfeld handelt oder nicht) geprüft werden, ob sie unzulässgie Zeichen enthalten. Die unzulässigen Zeichen sind in der ini-Datei [ERP_Item.ini](\\ruledesigner\RDF_Daten\Konfigurator\CustomVaulting\ERP_Item.ini) in Sektion "Settings" unter dem Key "InvalidCharacters" aufgelistet:
![invalid_characters](../doc/Pictures/Invalid_Characters.jpg) ![invalid_characters](../doc/Pictures/Invalid_Characters.jpg)
@@ -1894,7 +1913,7 @@ Zeichenbegrenzung = 400 - Aktuelle Anzahl an Zeichen im Textfeld [Automatische Z
- "{Zeichentyp}" muss durch das eigentliche, unzulässige Zeichen ersetzt werden, z.B. ";" - "{Zeichentyp}" muss durch das eigentliche, unzulässige Zeichen ersetzt werden, z.B. ";"
- "{Feldname}" muss durch den individuellen Feldnamen ersetzt werden. - "{Feldname}" muss durch den individuellen Feldnamen ersetzt werden.
- Falls mehrere unzulässige Zeichen gleichzeitig auftreten, sollen diese untereinander aufgelistet werden. - Falls mehrere unzulässige Zeichen gleichzeitig auftreten, können diese entweder untereinander in einer Messagebox aufgelistet werden. Alternativ (falls einfacher implementierbar) kann auch für jedes Feld, in dem ein unzulässiges Zeichen festgestellt wurde, eine eigene Messagebox ausgegeben werden
--- ---
#### Bezeichnung 1 #### Bezeichnung 1
@@ -2152,11 +2171,23 @@ Tritt eine der nachfolgenden aufgelisteten Fälle auf, soll eine ERROR-Messagebo
Teilenummer kann nicht ohne festgelegte Farbe migriert werden! Teilenummer kann nicht ohne festgelegte Farbe migriert werden!
--- ---
#### Änderungstext und Freigabevermerk #### Aenderungstext
Wenn die Länge des Änderungstextes oder Freigabevermerks eine Länge von 400 Zeichen überschreitet und in der Spalte "Überschriebene Werte" kein kürzerer Änderungstext eingetragen wurde, muss beim Klick auf den Button "Migrieren" eine ERROR-Messagebox erscheinen. Beim Feld Änderungstext, z.B. mit Text "*Änderungstext weist {Länge Änderungstext in Spalte 'SIVAS-Werte'} auf. Bitte auf 400 Zeichen verkürzen!*". Beim Feld "Freigabevermerk, z.B. mit Text "*Freigabevermerk weist {Länge Freigabevermerk in Spalte 'SIVAS-Werte'} auf. Bitte auf 400 Zeichen verkürzen!*" erscheinen. Wenn die Länge des Textes im Feld [Änderungstext](#änderungstext) eine Länge von 400 Zeichen überschreitet und in der Spalte "Überschriebene Werte" kein kürzerer Änderungstext eingetragen wurde, muss beim Klick auf den Button "Migrieren" eine ERROR-Messagebox (siehe nachfolgendes Bild) erscheinen:
Beispiel für Änderungstext:
![error_aenderungstext](../doc/Pictures/error_aenderungstext.jpg) ![error_aenderungstext](../doc/pictures/error_aenderungstext.jpg)
**messagebox-Text:**
Änderungstext bitte auf 400 Zeichen verkürzen!
#### Freigabevermerk
Wenn die Länge des Textes im Feld [Freigabevermerk](#freigabevermerk) eine Länge von 400 Zeichen überschreitet und in der Spalte "Überschriebene Werte" kein kürzerer Freigabevermerk eingetragen wurde, muss beim Klick auf den Button "Migrieren" eine ERROR-Messagebox (siehe nachfolgendes Bild) erscheinen:
![error_aenderungstext](../doc/pictures/error_freigabevermerk.jpg)
**messagebox-Text:**
Freigabevermerk bitte auf 400 Zeichen verkürzen!
### Tätigkeiten im Rahmen der Impfdateierstellung ### Tätigkeiten im Rahmen der Impfdateierstellung
@@ -2413,8 +2444,6 @@ Der eingetragene Wert im Feld [Dispolaufgruppe](#dispolaufgruppe) muss als gemap
#### ZusaetzlicheInformationen #### ZusaetzlicheInformationen
Die Werte aus den Feldern [Automatische Zusatzinformationen](#automatische-zusatzinformationen) und [Benutzerdefinierte Zusatzinformationen](#benutzerdefinierte-zusatzinformationen) müssen vor dem Eintragen in die Impfdatei zusammengesetzt werden Die Werte aus den Feldern [Automatische Zusatzinformationen](#automatische-zusatzinformationen) und [Benutzerdefinierte Zusatzinformationen](#benutzerdefinierte-zusatzinformationen) müssen vor dem Eintragen in die Impfdatei zusammengesetzt werden
### Tätigkeiten nach der Impfdateierstellung ### Tätigkeiten nach der Impfdateierstellung
1. Kopieren des aktuellen Standes der RuleDesigner-Datenbank (nachdem RDX-Prozess ausgeführt wurde). 1. Kopieren des aktuellen Standes der RuleDesigner-Datenbank (nachdem RDX-Prozess ausgeführt wurde).
+27 -83
View File
@@ -2,75 +2,12 @@ import tkinter as tk
#import ttkbootstrap as ttk #import ttkbootstrap as ttk
#from ttkbootstrap.constants import * #from ttkbootstrap.constants import *
from gui import App from gui import App
from caditem import CadItem from caditem import CadItem, GuiLogic
from controller import Controller, GuiLogic from controller import Controller
from manage_configs import Configs from manage_configs import Configs
import argparse import argparse
import os import os
demo_data = """
{
"parent_children_mapping": {
"400102130": [ "400102142" ],
"400102167": [ "821116004" ],
"400102168": [ "821116001" ],
"400102195": [ "822066075", "822066216", "822066154", "822066101",
"822064090", "822066196", "400102129", "822066217", "822066160",
"822066215", "913041045", "913011009", "911011057", "822064035",
"925011006", "911091041", "913051040", "911021112", "911021166",
"825006003", "912041005", "911011014", "911011009", "911021144",
"911021001", "913011016", "929055170", "913011010", "911021035",
"829416065", "712000151", "712000100" ],
"400102196": [ "400102125", "400102126", "400102130", "400102161",
"400102163", "400102165", "400102166", "400102167", "400102168",
"400102190", "400102195", "400102198", "400102246", "400102247",
"400102267", "400102272", "400102274", "400102275", "400102277",
"400102278", "400102282", "400102284", "400102417", "720002003",
"721001034", "821114025", "822064091", "822066085", "822996075",
"829416061", "829516004", "911021113", "911021181", "911021259",
"911091054", "911091096", "911091097", "911251013", "912011009",
"919050006", "924031058", "924031081" ],
"400102235": [ "400102236", "400102237", "400102238", "400102239",
"400102268", "911021143", "911021054", "911021055" ],
"400102236": [ "MA0000006" ],
"400102267": [ "400102235", "829416159", "829416077", "829416079",
"911021260", "911021147", "911251014" ],
"400102282": [ "822066026", "822066089", "919010052" ],
"821114025": [ "911081007", "821116053" ],
"821116004": [ "822026004" ],
"822064035": [ "822066065" ],
"822064091": [ "822066212", "822064093", "822066220", "822066200",
"912011010", "911021156", "822066201", "911071027", "913011109",
"911011070", "913011001", "710005021", "919010055", "720000008", "720000007" ],
"822064093": [ "822066204", "822066205", "822066206", "822066207", "822066208" ],
"822066075": [ "822066157", "822066162", "911261023" ],
"822066160": [ "MA0000004" ],
"822066162": [ "822064013" ],
"822066196": [ "MA0000008" ],
"822066220": [ "924031033" ],
"829416159": [ "829416089" ]
},
"red_ids": [ "400102274", "400102275", "400102190", "400102198", "400102161",
"400102277", "400102163", "400102278", "400102282", "400102284",
"400102195", "MA0000008", "MA0000004", "929055170", "400102267",
"400102235", "400102236", "MA0000006", "400102237", "400102238",
"400102239", "400102268", "829416159", "924031058", "924031081",
"822064091", "822066199", "822066200" ],
"gui_data": {
"asm_id": "400102190",
"teilenummer": "400102195",
"pdm_kategorie_neu": "Einzelteil",
"neuaufbau": "False",
"lebenszyklus_status_neu": "Serie",
"aus_halbzeug_neu": "True",
"zusatzinfos_auto_text": "Dies sind neue Zusatzinfos",
"cb_lebenszyklus_status_neu": ["Serie", "Prototyp"],
"cb_werkstofftyp_neu": ["Stahl", "Aluminium", "Kunst-/ Verbundstoff", "Schwermetall"]
},
"data": {}
}
"""
#"teilenummer": "400102195", assembly
class Environment: class Environment:
@@ -79,18 +16,22 @@ class Environment:
self.data_dir = os.environ.get('CREMIG_DATA') self.data_dir = os.environ.get('CREMIG_DATA')
self.out_dir = os.environ.get('CREMIG_WORK') self.out_dir = os.environ.get('CREMIG_WORK')
self.cfg_dir = os.environ.get('CREMIG_CFG') self.cfg_dir = os.environ.get('CREMIG_CFG')
self.log_dir = os.environ.get('CREMIG_LOG')
self.ruledesigner_csv_filename = os.environ.get('RD_DATABASE_NAME') self.ruledesigner_csv_filename = os.environ.get('RD_DATABASE_NAME')
def build_gui(model, configs): def build_gui(model, configs, env, sivasid=None, uselocal=True):
root = tk.Tk() root = tk.Tk()
#root = ttk.Window() #root = ttk.Window()
app = App(root, configs) app = App(root, configs)
controller = Controller(model, app) controller = Controller(model, app)
controller.set_env(configs.get_env()) controller.set_env(env)
controller.set_config(configs)
if sivasid:
controller.get_csv_files_of_asm(sivasid, load_local_bom=uselocal, load_local_teilestamm=uselocal, load_local_rd_ids=uselocal)
logic = GuiLogic(model, configs) logic = GuiLogic(model, configs)
controller.add_logic(logic) model.add_logic(logic)
# um ohne Observer pattern auch Rückmeldungen geben zu können # um ohne Observer pattern auch Rückmeldungen geben zu können
app.set_controller(controller) app.set_controller(controller)
@@ -98,33 +39,36 @@ def build_gui(model, configs):
# Daten des Modells in der Oberfläche darstellen # Daten des Modells in der Oberfläche darstellen
controller.refresh_gui() controller.refresh_gui()
app.mainloop() app.mainloop()
if __name__ == '__main__': if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Das Programm ermöglicht einw graphisch unterstützte Migration eines Teiles oder Assemblies von Creo nach SolidEdge. Erzeugt eine korrekte Impfdatei.', prog='CreoMigrateGui') parser = argparse.ArgumentParser(description='Das Programm ermöglicht einw graphisch unterstützte Migration eines Teiles oder Assemblies von Creo nach SolidEdge. Erzeugt eine korrekte Impfdatei.', prog='CreoMigrateGui')
parser.add_argument('-s', '--sivasid', action='store', help='Eingabe der SIVAS-Teilenummer, für die der Migrationsstatus angezeigt werden soll', metavar="id") parser.add_argument('-s', '--sivasid', action='store', help='Eingabe der SIVAS-Teilenummer, für die der Migrationsstatus angezeigt werden soll')
parser.add_argument('-d', '--demo', action='store_true', help='arbeitet ohne Server. Lädt Testdaten ein um nur eine Oberfläche darzustellen') parser.add_argument('-d', '--demo', action='store_true', help='arbeitet ohne Server. Lädt Testdaten ein um nur eine Oberfläche darzustellen')
parser.add_argument('-l', '--uselocal', action='store_true', help='Verbinde dich nicht zur Datenbank. Benutzer alle lokalen Dateien (falls vorhanden) für die gegebene asm-id')
args = parser.parse_args() args = parser.parse_args()
environment = Environment() environment = Environment()
output_dir = environment.out_dir
data_dir = environment.data_dir
configs = Configs(environment.cfg_dir) configs = Configs(environment.cfg_dir)
configs.set_env(environment) configs.set_data_dir(data_dir)
model = CadItem() model = CadItem()
if args.demo: if args.sivasid:
model.from_json(demo_data) sivasid = args.sivasid.strip()
build_gui(model, configs)
elif args.sivasid: output_dir = environment.out_dir
id = args.sivasid assembl_path = os.path.join(output_dir, sivasid + '.json')
path = os.path.join(output_dir, id + '.json') if os.path.exists(assembl_path):
if os.path.exist(path): # wenn schon einmal das assembly als json abgespeichert wurde, dann dieses laden
model.load(demo_data) model.load(assembl_path)
build_gui(model, configs) else:
# die Gui aufbauen
build_gui(model, configs, environment, sivasid, args.uselocal)
else: else:
parser.print_help() build_gui(model, configs, environment)
+2434 -77
View File
File diff suppressed because it is too large Load Diff
+339 -311
View File
@@ -1,271 +1,136 @@
import update_database from manage_configs import SivasBOM, RuleDesignerDatabaseConfig, MigrationStatus, SivasTeilestamm, BOMConfig
import warnings
#Wegen Pandas Deprecation eingebaut
warnings.filterwarnings("ignore", category=DeprecationWarning)
import argparse import argparse
import os import os
import json
import pandas as pd
import openpyxl import openpyxl
from itertools import zip_longest
""" """
Dieses Programm kann: Dieses Programm kann:
- eine Excel-Datei exportieren, in der alle Teilenummern aufgelistet sind, die in Verbindung mit einer angegebenen Nummer migriert werden müssen. - eine Excel-Datei exportieren, in der alle Teilenummern aufgelistet sind, die in Verbindung mit einer angegebenen Nummer migriert werden müssen.
Sie gibt dabei Auskunft darüber, welche Teilenummern bereits migriert wurden und welche noch migriert werden müssen. Sie gibt dabei Auskunft darüber, welche Teilenummern bereits migriert wurden und welche noch migriert werden müssen.
- die oben beschriebene Darstellung in einer Excel-Datei auch als Treeview auf der Kommandozeile darstellen - die oben Darstellung in der Excel-Datei als Baum in der Konsole ausgeben
""" """
class Environment: class GetExcludedIDsFromCFG(argparse.Action):
def __call__(self, parser, namespace, values, option_string = None):
bom_config = BOMConfig(os.path.dirname(values[0]), os.path.basename(values[0]))
excluded_ids = bom_config.get_excluded_ids(values[1])
setattr(namespace, self.dest, excluded_ids)
def __init__(self): class LStrip(argparse.Action):
self.lib_dir = os.environ.get('CREMIG_LIB') def __call__(self, parser, namespace, values, option_string = None):
self.data_dir = os.environ.get('CREMIG_DATA') setattr(namespace, self.dest, values.lstrip())
self.out_dir = os.environ.get('CREMIG_WORK')
self.ruledesigner_csv_filename = os.environ.get('RD_DATABASE_NAME')
self.vba_macro_filename = os.environ.get('VBA_MACRO_NAME')
self.vba_macro_filepath = os.path.join(self.lib_dir, self.vba_macro_filename)
class LocateSQLCredentials(argparse.Action):
class Partnumbers: def __call__(self, parser, namespace, values, option_string = None):
if not os.path.isfile(os.environ.get("RD_SQL_DATABASE_CREDENTIALS")):
def __init__(self, filename: str, file_dir: str): print(f"ACHTUNG: Blau hinterlegte Nummern (Teilenummern die ins PDM migriert wurden, aber aktuell nicht freigegeben sind) werden nicht dargestellt, da nicht auf die Login-Daten für die RD-SQL-Datenbank zugegriffen werden kann. Bitte prüfen, ob die Login-Datei '{os.environ.get("RD_SQL_DATABASE_CREDENTIALS")}' existiert. Auch prüfen, ob die Netzlaufwerke verbunden sind!")
self.file_dir = file_dir setattr(namespace, self.dest, True)
self.filename = filename.rsplit(".")[0]
def load_from_json(self):
"""Reads partnumbers from a json-file"""
config_path = os.path.join(self.file_dir, self.filename + ".json")
try:
with open(config_path, encoding='utf-8') as json_file:
return json.load(json_file)
except FileNotFoundError:
update_database.get_sivas_dbase(self.filename, self.file_dir)
return self.load_from_json()
def load_from_csv(self):
"""Reads partnumbers from a csv-file"""
config_path = os.path.join(self.file_dir, self.filename + ".csv")
try:
df = pd.read_csv(config_path, sep=';', converters={"Teilenummern":str})
return tuple(df["Teilenummern"])
except FileNotFoundError:
update_database.get_rd_dbase(self.file_dir)
return self.load_from_csv()
class SivasPartnumbers(Partnumbers):
def __init__(self, main_sivas_id: str, file_dir: str):
self.file_dir = file_dir
self.main_sivas_id = main_sivas_id
self._partnumbers = None
super().__init__(file_dir=self.file_dir, filename=self.main_sivas_id)
def lazy_partnumber_init(function):
"""Decorator prevents time-consuming initialization of sivas partnumbers if method doesn't require them"""
def wrapper(self):
if self._partnumbers is None:
self._partnumbers = self.__class__.mro()[1].load_from_json(self) # Using super() isn't possible here
return function(self)
return wrapper
@lazy_partnumber_init
def get_partnumbers(self) -> set:
"""Returns all partnumbers (id's) of the provided json-file"""
ids = set()
for child_id, top_level_assemblies_of_child in self._partnumbers.items():
ids.add(child_id)
for top_level_assembly in top_level_assemblies_of_child:
top_level_assembly_id = top_level_assembly["Parent"]
ids.add(top_level_assembly_id)
return ids
def get_longest_partnumber(self) -> str:
"""Returns the longest partnumber in the provided json-file"""
return max(self.get_partnumbers())
@lazy_partnumber_init
def get_ordered_parent_children(self, no_duplicates: bool = False) -> dict:
"""Replicates the partnumber structure of the given BOM (bill of material) from sivas. The Order of the partnumbers is identical to the position numbers in the BOM"""
unordered_parent_children = {}
for parents in self._partnumbers:
for children in self._partnumbers[parents]:
if children["Parent"] not in unordered_parent_children:
unordered_parent_children[children["Parent"]] = {}
pos = children["Position"].lstrip(".").split("/")[0]
pos_in_list = int(pos)
unordered_parent_children[children["Parent"]][pos_in_list] = parents
# Second dict necessary, because children aren't sorted according to their position numbers in the SIVAS-BOM
ordered_parent_children = {}
for key, values in unordered_parent_children.items():
for subkey, subvalue in sorted(values.items()):
if key not in ordered_parent_children:
ordered_parent_children[key] = []
ordered_parent_children[key].append(subvalue)
return ordered_parent_children
@lazy_partnumber_init
def get_max_bom_depth(self) -> int:
"""Returns the maximum nesting-depth (level) of the provided assembly partnumber as an integer"""
bom_levels = []
for values in self._partnumbers.values():
for value in values:
current_bom_level = value["Position"].count(".")
bom_levels.append(current_bom_level)
return max(bom_levels)
@lazy_partnumber_init
def get_partnumber_descriptions(self) -> dict:
descriptions = {}
for parent, values in self._partnumbers.items():
for value in values:
descriptions[parent] = value["Bezeichnung"]
return descriptions
class RuleDesignerPartnumbers(Partnumbers):
def __init__(self, ruledesigner_ids_dir: str, ruledesigner_ids_filename: str):
self.ruledesigner_ids_dir = ruledesigner_ids_dir
self.ruledesigner_ids_filename = ruledesigner_ids_filename
super().__init__(file_dir=self.ruledesigner_ids_dir, filename=self.ruledesigner_ids_filename)
def get_partnumbers(self):
return super().load_from_csv()
def update_database(self):
return update_database.get_rd_dbase(self.ruledesigner_ids_dir)
class SivasRuleDesignerComparison:
def __init__(self, sivas_ids_dir, sivas_main_id, rd_ids_dir, rd_ids_filename):
self.sivas = SivasPartnumbers(main_sivas_id=sivas_main_id, file_dir=sivas_ids_dir)
self.ruledesigner = RuleDesignerPartnumbers(ruledesigner_ids_dir=rd_ids_dir, ruledesigner_ids_filename=rd_ids_filename)
def get_migration_status(self) -> dict:
"""Checks if given sivas-partnumbers have been migrated been migrated into RuleDesigner"""
sivas_ids = self.sivas.get_partnumbers()
ruledesigner_ids = self.ruledesigner.get_partnumbers()
migration_completed = {}
for sivas_partnumber in sivas_ids:
migration_completed[sivas_partnumber] = True if sivas_partnumber in ruledesigner_ids else False
return migration_completed
class ExcelExport: class ExcelExport:
def __init__(self, main_id, sivas_ids_file_dir, rd_ids_file_dir, rd_ids_filename): def __init__(self,
self.main_id = main_id asm_id,
self.environment = Environment() asm_json_dir,
self._sivas = SivasPartnumbers(main_sivas_id=main_id, file_dir=sivas_ids_file_dir) asm_json_filename,
self._ruledesigner = RuleDesignerPartnumbers(ruledesigner_ids_dir=rd_ids_file_dir, ruledesigner_ids_filename=rd_ids_filename) asm_csv_dir,
self._comparison = SivasRuleDesignerComparison(sivas_ids_dir=sivas_ids_file_dir, sivas_main_id=main_id, rd_ids_dir=rd_ids_file_dir, rd_ids_filename=rd_ids_filename) asm_csv_filename,
self._parent_children = self._sivas.get_ordered_parent_children() rd_dbase_dir,
self._ruledesigner_ids = self._ruledesigner.get_partnumbers() rd_dbase_filename,
load_local_asm_json,
load_local_asm_csv,
load_local_rd_dbase,
no_blue_ids):
self.asm_id = asm_id
self.asm_data = SivasBOM(asm_json_dir, asm_json_filename, load_local_asm_json)
self.asm_metadata = SivasTeilestamm(asm_csv_dir, asm_csv_filename, load_local_asm_csv)
self.rd_data = RuleDesignerDatabaseConfig(rd_dbase_dir, rd_dbase_filename, load_local_rd_dbase)
self._migration_status = None
@property
def migration_status(self):
if self._migration_status is None:
self._migration_status = MigrationStatus(self.asm_data.child_ids, self.rd_data.ids)
return self._migration_status
def write_excel(self): def write_excel(self):
data = self._create_excel_data() data = self._create_excel_data()
output_dir = environment.out_dir out_dir = os.environ.get("CREMIG_WORK")
out_path = os.path.join(out_dir, self.asm_id + ".xlsm")
destiny_filepath = os.path.join(output_dir, self.main_id + ".xlsm") workbook_path = os.path.join(os.environ.get("CREMIG_LIB"), os.environ.get("VBA_MACRO_NAME"))
workbook = openpyxl.load_workbook(workbook_path, keep_vba=True)
workbook = openpyxl.load_workbook(self.environment.vba_macro_filepath, keep_vba=True)
worksheet = workbook.active worksheet = workbook.active
# Headers # Spaltenüberschriften
for header, column in zip(data, worksheet.iter_cols(min_row=1, max_col=len(data), max_row=1)): for header, column in zip(data, worksheet.iter_cols(min_row=1, max_col=len(data), max_row=1)):
for cell in column: for cell in column:
cell.value = header cell.value = header
# Values below Headers # Werte unter Spaltenüberschriften
for value, column in zip(data.values(), worksheet.iter_cols(min_row=2, max_col=len(data), max_row=len(data["Sortierung"])+1)): for value, column in zip(data.values(), worksheet.iter_cols(min_row=2, max_col=len(data), max_row=len(data["Sortierung"])+1)):
for cell, element in zip(column, value): for cell, element in zip(column, value):
cell.value = element cell.value = element
# Renaming the sheet is necessary, because it triggers the execution of the VBA-Macro # Umbenennung des Blattes erforderlich, da die Umbenennung die Ausführung des VBA-Makros triggert.
# The renaming must be performed AFTER inserting the data into the spreadsheet, because the conditional formatting, which is part of the macro, can't be performed # Die Umbenennung muss NACH dem Einfügen der Daten in das Blatt erfolgen, da die bedingte Formatierung,
# when no data is in the spreadsheet # die ebenfalls Bestandteil des Makros ist, nicht ausgeführt werden kann, solange sich keine Daten im Blatt befinden
worksheet.title = "Ergebnis" worksheet.title = "Ergebnis"
workbook.save(destiny_filepath) workbook.save(out_path)
print(f"Excel-Datei erfolgreich in '{output_dir}' geschrieben...") print(f"Excel-Datei erfolgreich in '{out_dir}' geschrieben...")
def _create_excel_data(self) -> dict: def _create_excel_data(self) -> dict:
# Columns in excel-spreadsheet: Sortierung, Teilenummer, Bezeichnung, Bestandsabfrage, Teilebeurteilung, Zusatzbemerkung # Spalten im Arbeitsblatt: Sortierung, Teilenummer, Bezeichnung, Bestandsabfrage, Teilebeurteilung, Zusatzbemerkung
# Sortierung: Minus-separated hierarchy of the partnumber in the BOM structure # Sortierung: Minus-separierte Hierarchie der Teilenummern in der Stücklistenstruktur
# Teilenummer: SIVAS-partnumber # Teilenummer: SIVAS-Teilenummer
# Bezeichnung: SIVAS-description of the partnumber # Bezeichnung: SIVAS-Bezeichnung der Teilenummer
# Migrationsstatus: "IMPORTIEREN" = partnumber hasn't been migrated yet, "VERFÜGBAR" = partnumber has been migrated # Migrationsstatus: "IMPORTIEREN" = Migration ausstehend, "VERFÜGBAR" = Migration abgeschlossen
# All the other columns remain empty, because their values are entered in the excel spreadsheet # Alle weiteren Spalten bleiben leer, da sie händisch vom User zu befüllen sind
sorting = self._create_sorting_string() sorting = self._create_sorting_string()
migrated = self._comparison.get_migration_status() migrated_ids = self.migration_status.ids_in_rd
descriptions = self._sivas.get_partnumber_descriptions() child_descriptions:dict = self.asm_data.get_prop_val_for_all_ids("Bezeichnung")
parent_description:str = self.asm_metadata.get_property_values("Bezeichnung1")
descriptions = child_descriptions.copy()
descriptions[asm_id] = parent_description
prt_num = [] prt_num = []
description = [] description = []
migration_status = [] migration_status = []
evaluation = [] assessment = []
comment = [] comment = []
for partnumber_string in sorting: for id_str in sorting:
partnumber = partnumber_string.split("-")[-1] id = id_str.split("-")[-1]
prt_num.append(partnumber) prt_num.append(id)
if partnumber not in descriptions: assessment.append('')
description.append("")
else:
description.append(descriptions[partnumber])
migration_status.append("VERFÜGBAR" if migrated[partnumber] is True else "IMPORTIEREN")
evaluation.append('')
comment.append('') comment.append('')
if id not in descriptions:
description.append("")
else:
description.append(descriptions[id])
if id in migrated_ids:
if id in self.migration_status.ids_in_progress:
migration_status.append("PDM-Migration abgeschlossen")
else:
migration_status.append("Migration abgeschlossen (freigegeben)")
else:
migration_status.append("Migration ausstehend")
data = { data = {
"Sortierung": sorting, "Sortierung": sorting,
"Teilenummer": prt_num, "Teilenummer": prt_num,
"Bezeichnung": description, "Bezeichnung": description,
"Migrationsstatus": migration_status, "Migrationsstatus": migration_status,
"Beurteilung": evaluation, "Beurteilung": assessment,
"Bemerkung": comment "Bemerkung": comment
} }
return data return data
@@ -284,21 +149,21 @@ class ExcelExport:
""" """
if parent is None: if parent is None:
parent = self.main_id parent = self.asm_id
if sorting_strings is None: if sorting_strings is None:
sorting_strings = [parent] sorting_strings = [parent]
children = self._parent_children[parent] parent_children = self.asm_data.parent_children
children = parent_children[parent]
for child in children: for child in children:
sorting_strings.append(f"{previous_parents}-{parent}-{child}".lstrip("-")) sorting_strings.append(f"{previous_parents}-{parent}-{child}".lstrip("-"))
if child in self._parent_children: if child in parent_children:
self._create_sorting_string(parent=child, previous_parents=previous_parents + f"-{parent}", sorting_strings=sorting_strings) self._create_sorting_string(parent=child, previous_parents=previous_parents + f"-{parent}", sorting_strings=sorting_strings)
return sorting_strings return sorting_strings
class Treeview: class Treeview:
@@ -315,144 +180,307 @@ class Treeview:
console_colors = {"RED": "\033[41m", console_colors = {"RED": "\033[41m",
"GREEN": "\033[42m", "GREEN": "\033[42m",
"BLUE": "\033[44m",
"RESET": "\033[0m" "RESET": "\033[0m"
} }
def __init__(self, main_partnumber, sivas_src_file, rd_src_dir, rd_src_file): def __init__(self,
self.main_partnumber = main_partnumber asm_id:str,
self._sivas = SivasPartnumbers(main_sivas_id=main_partnumber, file_dir=sivas_src_file) asm_json_dir:str,
self._ruledesigner = RuleDesignerPartnumbers(ruledesigner_ids_dir=rd_src_dir, ruledesigner_ids_filename=rd_src_file) asm_json_filename:str,
self._sivas_rd_comparison = SivasRuleDesignerComparison(sivas_main_id=main_partnumber, sivas_ids_dir=sivas_src_file, rd_ids_dir=rd_src_dir, rd_ids_filename=rd_src_file) asm_csv_dir:str,
self._parent_children = self._sivas.get_ordered_parent_children() asm_csv_filename:str,
self._descriptions = self._sivas.get_partnumber_descriptions() rd_dbase_dir:str,
self._max_tree_depth = self._sivas.get_max_bom_depth() rd_dbase_filename:bool=False,
self._longest_partnumber = self._sivas.get_longest_partnumber() load_local_asm_json:bool=False,
self._migration_status = self._sivas_rd_comparison.get_migration_status() load_local_asm_csv:bool=False,
load_local_rd_dbase:bool=False,
no_blue_ids:bool=False,
excluded_bom_ids:list=None,
excluded_summary_ids:list=None):
self.asm_id = asm_id
self.asm_bom = SivasBOM(asm_id, asm_json_dir, asm_json_filename, load_local_asm_json, excluded_bom_ids)
self.asm_teilestamm = SivasTeilestamm(asm_csv_dir, asm_csv_filename, load_local_asm_csv)
self.rd_data = RuleDesignerDatabaseConfig(rd_dbase_dir, rd_dbase_filename, load_local_rd_dbase)
self.all_excluded_summary_ids = excluded_summary_ids
self._excluded_summary_ids_in_bom = None
self.no_blue_ids = no_blue_ids
self._migration_status = None
self._longest_entry = None
@property
def migration_status(self):
if self._migration_status is None:
self._migration_status = MigrationStatus(self.asm_bom.child_ids, self.rd_data.ids)
return self._migration_status
@property
def longest_entry(self):
if self._longest_entry is None:
longest_color_code = max(Treeview.console_colors.values(), key=len)
longest_connector_symbol = max(Treeview.connector_symbols.values(), key=len)
padding_after_id = 2
if self._longest_entry is None:
self._longest_entry = (self.asm_bom.max_bom_depth) * len(Treeview.prefix_types["PIPE"]) \
+ len(longest_connector_symbol) \
+ len(longest_color_code) \
+ len(self.asm_bom.longest_child_id) \
+ len(Treeview.console_colors["RESET"]) \
+ padding_after_id
return self._longest_entry
def _add_asm_id_to_bom(self):
"""Standardmäßig ist die oberste Baugruppennummer kein Bestandteil der JSON-Datei, in der die Baugruppenstruktur aufgelistet ist und
die über das Programm 'Sivas2Json' von Hr. Jakob generiert wird. Damit der Baum die Bezeichnung der obersten Baugruppennummer im
Baum angezeigt wird ist es jedoch erforderlich, dass die Nummer mitsamt ihrer Bezeichnung in der JSON enthalten ist"""
metadata = {"Bezeichnung": self.asm_teilestamm.get_property_values("Bezeichnung1"),
"Parent": None,
"Position": "10/0"}
self.asm_bom.extend_asm_bom(self.asm_id, metadata)
def generate_tree(self): def generate_tree(self):
self._tree_header() self._add_asm_id_to_bom()
self._tree_body() self._print_tree()
self._tree_summary() self._print_summary()
def _tree_header(self):
"""Prints root number (number for which the user wants to see the tree) to the console"""
background_color = self._set_text_background_color(self.main_partnumber) def _print_tree(self, parent_id=None, prefix=""):
print(f"{background_color}{self.main_partnumber}{Treeview.console_colors['RESET']}")
def _tree_body(self, parent_id=None, prefix=""): """Gibt die Baugruppenstruktur in Form eines Baumes in der Konsole aus"""
"""Prints the body (all partnumbers except root/main-partnumber) of the tree to the console""" parent_children = self.asm_bom.parent_children
children_ids = parent_children[parent_id]
if parent_id is None: for i, id in enumerate(children_ids):
parent_id = self.main_partnumber
children_ids = self._parent_children[parent_id]
for index, child_id in enumerate(children_ids):
is_last_assembly_child = self._last_child_check(index, children_ids) last_child = self._last_child_check(i, children_ids)
connector_symbol = self._set_connector_symbol(id, last_child)
background_color = self._set_background_color(id)
connector_symbol = self._set_connector_symbol(is_last_assembly_child) self._print_entry(id, prefix, connector_symbol, background_color)
partnumber_background_color = self._set_text_background_color(child_id)
self._print_entry(child_id, prefix, connector_symbol, partnumber_background_color) if id in parent_children:
next_prefix = self._set_next_prefix(prefix, id, last_child)
self._print_tree(parent_id=id, prefix=next_prefix)
if child_id in self._parent_children: def _remove_ids_from_summary_amount(self, ids: list) -> list:
next_prefix = self._prefix(prefix, is_last_assembly_child) """
self._tree_body(parent_id=child_id, prefix=next_prefix) Reduziert die Anzahl in der Zusammenfassung (z.B. der nicht migrierten Teilenummern),
um die Anzahl an Teilenummern, die vom User aus der Zusammenfassung ausgeschlossen wurden
"""
def _tree_summary(self): if self.all_excluded_summary_ids is None:
return ids
return list(filter(lambda id: id not in self.excluded_summary_ids_in_bom, ids))
amount_all_sivas_ids = len(self._migration_status) @property
amount_migrated_ids = sum(migration_status == True for migration_status in self._migration_status.values()) def excluded_summary_ids_in_bom(self) -> list:
amount_unmigrated_ids = amount_all_sivas_ids - amount_migrated_ids """ Gibt alle Teilenummern zurück, die im Baum vorliegen, aber nicht in der Anzahl der Zusammenfassung enthalten sein sollen"""
progress = int(amount_migrated_ids / amount_all_sivas_ids * 100) if self._excluded_summary_ids_in_bom is None:
self._excluded_summary_ids_in_bom = list(filter(lambda id: id in self.asm_bom.bom_data, self.all_excluded_summary_ids))
return self._excluded_summary_ids_in_bom
def _print_summary(self):
ids_in_rd = self.migration_status.ids_in_rd
ids_pending = self.migration_status.ids_pending
amount_in_rd = len(self._remove_ids_from_summary_amount(ids_in_rd))
amount_pending = len(self._remove_ids_from_summary_amount(ids_pending))
if not self.no_blue_ids:
ids_in_progress = self.migration_status.ids_in_progress
amount_in_work = len(self._remove_ids_from_summary_amount(ids_in_progress))
amount_released = amount_in_rd - amount_in_work
child_ids = self.asm_bom.child_ids
progress = int(amount_in_rd / len(self._remove_ids_from_summary_amount(child_ids)) * 100)
column_width = 5 column_width = 5
border_padding = "".ljust(column_width, "") border_padding = "".ljust(column_width, "")
empty_padding = "".ljust(column_width, " ") empty_padding = "".ljust(column_width, " ")
print(f"""
╭─────────────────────────────────────{border_padding} red_entry = f"{Treeview.console_colors['RED'] } {Treeview.console_colors['RESET']}│ Migration ausstehend │ {str(amount_pending).ljust(column_width)}"
│ Auswertung {empty_padding}
├───────────────────────────────────┬─{border_padding} if not self.no_blue_ids:
│ Anzahl abgeschlossene Migrationen{str(amount_migrated_ids).ljust(column_width)} blue_entry = f"{Treeview.console_colors['BLUE'] } {Treeview.console_colors['RESET']}│ PDM-Migration abgeschlossen {str(amount_in_work).ljust(column_width)}\n"
│ Anzahl fehlende Migrationen {str(amount_unmigrated_ids).ljust(column_width)} green_entry = f"{Treeview.console_colors['GREEN']} {Treeview.console_colors['RESET']}│ Migration abgeschlossen (Freigegeben){str(amount_released).ljust(column_width)}\n"
├───────────────────────────────────┼─{border_padding}
│ Migrationsfortschritt │ {f"{progress}%".ljust(column_width)} else:
╰───────────────────────────────────┴─{border_padding} blue_entry = ""
""") green_entry = f"{Treeview.console_colors['GREEN']} {Treeview.console_colors['RESET']}│ Migration abgeschlossen │ {str(amount_in_rd).ljust(column_width)}\n"
red_entry = f"{Treeview.console_colors['RED'] } {Treeview.console_colors['RESET']}│ Migration ausstehend │ {str(amount_pending).ljust(column_width)}"
header = f"""
╭───────────────────────────────────────────{border_padding}
│ Auswertung {empty_padding}
├─┬───────────────────────────────────────┬─{border_padding}
"""
progress_segment = f"""
├─┴───────────────────────────────────────┼─{border_padding}
│ Migrationsfortschritt │ {f"{progress}%".ljust(column_width)}
"""
bottom_row = f"╰─────────────────────────────────────────┴─{border_padding}"
exclusion_description = ""
excluded_id_list = ""
if self.asm_bom.excluded_ids_in_bom or self.excluded_summary_ids_in_bom:
exclusion_description = f"""├─────────────────────────────────────────┴─{border_padding}
{empty_padding}
├───────────────────────────────────────────{border_padding}
│ Ausgeschlossene Teilenummern {empty_padding}
│──────────────────────┬────────────────────{border_padding}
│ Baum │ Auswertung {empty_padding}
├──────────────────────┼────────────────────{border_padding}
"""
for bom_id, smry_id in zip_longest(self.asm_bom.excluded_ids_in_bom, self.excluded_summary_ids_in_bom, fillvalue=9*" "):
excluded_id_list += f"{ bom_id}{smry_id} {empty_padding}\n"
bottom_row = f"╰──────────────────────┴────────────────────{border_padding}"
print(header + green_entry + blue_entry + red_entry + progress_segment + exclusion_description + excluded_id_list + bottom_row)
def _print_entry(self, child_id, prefix, connector, color): def _print_entry(self, child_id, prefix, connector, color):
"""Prints tree entry""" """Eintrag in die Konsole drucken"""
# Necessary for calculating the padding-width after the partnumber text_before_description = f"{prefix}{connector}{color}{child_id}{Treeview.console_colors['RESET']}".ljust(self.longest_entry)
longest_entry = self._max_tree_depth * len(Treeview.prefix_types["PIPE"]) \ description = self.asm_bom.get_prop_val_for_single_id(child_id, "Bezeichnung")
+ len(connector) \
+ len(self._longest_partnumber) \
+ len(Treeview.console_colors["RESET"]) \
+ len(Treeview.console_colors["RED"]) # other color codes (ansi escape sequences) could have been used instead since they all have the same length
text_before_description = f"{prefix}{connector}{color}{child_id}{Treeview.console_colors['RESET']}".ljust(longest_entry) print(f"{text_before_description}{description}")
description = self._descriptions[child_id]
print(f"{text_before_description} {description}")
def _last_child_check(self, child_index, children): def _last_child_check(self, child_idx, children_ids):
"""Checks, if current child is the last child of the assembly""" """Prüft, ob aktuelle ID das letzte Kind der Baugruppe ist"""
return True if child_index == len(children) - 1 else False return True if child_idx == len(children_ids) - 1 else False
def _set_connector_symbol(self, child_is_last_child): def _set_connector_symbol(self, child_id, last_child):
"""Chooses connector symbol for current tree entry""" """Legt Verbindungssymbol für aktuellen Eintrag im Baum fest"""
return Treeview.connector_symbols["ELBOW"] if child_is_last_child else Treeview.connector_symbols["T"] if child_id == self.asm_id: # Oberste Baugruppennummer wird immer ohne Verbindersymbol dargestellt
return ""
if not last_child:
return Treeview.connector_symbols["T"]
return Treeview.connector_symbols["ELBOW"]
def _prefix(self, prefix, child_is_last_child): def _set_next_prefix(self, prefix, child_id, last_child):
"""Creates prefix (part before the connector symbol) for each tree entry""" """Legt den Teil VOR dem Verbindersymbol für den nächsten Eintrag im Baum fest"""
prefix += Treeview.prefix_types["EMPTY"] if child_is_last_child else Treeview.prefix_types["PIPE"] if child_id == self.asm_id: # Erste Stücklistenposition der obersten Baugruppennummer hat nie Präfix
return ""
prefix += Treeview.prefix_types["EMPTY"] if last_child else Treeview.prefix_types["PIPE"]
return prefix return prefix
def _set_text_background_color(self, partnumber): def _set_background_color(self, id):
"""Sets background color of partnumber in console depending on its migration status """Legt Hintergrundfarbe der Teilenummer basierend auf ihrem Migrationsstatus fest:
- Migration completed: green
- Migration pending: red"""
return Treeview.console_colors["GREEN"] if self._migration_status[partnumber] is True else Treeview.console_colors["RED"] - grün: Migration vollständig abgeschlossen und freigegeben
- blau: Migration ins PDM abgeschlossen
- rot: Migration ausstehend"""
if id in self.migration_status.ids_pending:
return Treeview.console_colors["RED"]
if not self.no_blue_ids:
if id in self.migration_status.ids_in_progress:
return Treeview.console_colors["BLUE"]
return Treeview.console_colors["GREEN"]
if __name__ == '__main__': if __name__ == '__main__':
parser = argparse.ArgumentParser(description='Das Programm gibt Auskunft über den aktuellen Migrationsstand', prog='compare_lists')
parser.add_argument('-s', '--sivasid', action='store', required=True, help='Eingabe der SIVAS-Teilenummer, für die der Migrationsstatus angezeigt werden soll', metavar="id") def main():
parser.add_argument('-t', '--tree', action='store_true', help='Erzeugt Baumdarstellung aller Teilenummern. grün = Teilenummer vorhanden, rot = Migration ausstehend')
parser.add_argument('-e', '--excel', action='store_true', help='Erzeugt Excel-Datei in der alle Teilenummern, die migriert werden müssen, aufgelistet sind')
args = parser.parse_args() parser = argparse.ArgumentParser(description='Programm gibt Auskunft über den aktuellen Migrationsstand einer SIVAS-Teilenummer',
prog='compare_lists',
formatter_class=lambda prog: argparse.HelpFormatter(prog, max_help_position=50)) # Hilfetext auch bei längeren Argumenten in gleicher Zeile wie Argument darstellen
environment = Environment() # Custom Actions
parser.register("action", "GetIDsFromCFG", GetExcludedIDsFromCFG)
parser.register("action", "lstrip", LStrip)
parser.register("action", "LocateSQLCredentials", LocateSQLCredentials)
if args.excel: parser.add_argument('sivas_id', action='lstrip', help='Teilenummer, für die Migrationsüberblick generiert werden soll.', metavar="SIVAS-Teilenummer")
num = args.sivasid.lstrip() parser.add_argument('output_type', choices=["tree", "excel"], help="'tree' = Darstellung des Überblicks als Baum in der Konsole. 'excel' = Export des Überblicks als Excel")
excel_comparison = ExcelExport(num, environment.data_dir, environment.data_dir, environment.ruledesigner_csv_filename) parser.add_argument('--rd_ids_filepath', action='store', default=os.path.join(os.environ.get("CREMIG_DATA"), "RD_Teilenummern.csv"), help='Verzeichnis der CSV-Datei mit den RuleDesigner-Nummern. Default: $CREMIG_DATA', metavar="filepath")
excel_comparison.write_excel() parser.add_argument('--local_rd_ids', action='store_true', default=False, help='Lokales laden der CSV mit den RuleDesigner-Nummern (RD-Teilenummer.csv) statt Kopieren von Server')
elif args.tree: parser.add_argument('--bom_filedir', action='store', default=os.environ.get("CREMIG_DATA"),help='Verzeichnis der JSON-Datei mit den Stücklisteninformationen. Default: $CREMIG_DATA', metavar='dir')
num = args.sivasid.lstrip() parser.add_argument('--local_bom', action='store_true', default=False, help='Lokales laden der JSON mit den Stücklisteninformationen statt Generierung')
treeview_comparison = Treeview(num, environment.data_dir, environment.data_dir, environment.ruledesigner_csv_filename) parser.add_argument('--teilestamm_filedir', action='store', default=os.environ.get("CREMIG_DATA"), help='Verzeichnis der CSV mit den SIVAS-Teilestamminformationen. Default: $CREMIG_DATA', metavar='dir')
treeview_comparison.generate_tree() parser.add_argument('--local_teilestamm', action='store_true', default=False, help='Lokales Laden der CSV mit den Teilestamminformationen statt Generierung')
else: parser.add_argument('--no_blue_ids', action="store_true", default=False, help='Nummern, die in RD vorliegen, aber nicht freigegeben sind, gleich wie freigegeben Nummern einfärben')
parser.print_help()
exclude_from_overview = parser.add_mutually_exclusive_group()
exclude_from_overview.add_argument('--rm_bom_ids_str', action="store", nargs="*", default=None, dest="excluded_bom_ids", help="Angabe aller Nummern, die vom Migrationsüberblick ausgeschlossen sein sollen", metavar="id1 id2")
exclude_from_overview.add_argument('--rm_bom_ids_cfg', action="GetIDsFromCFG", nargs=2, default=None, dest="excluded_bom_ids", help="cfg-Pfad & Sektion, in der Nummern aufgelistet sind, die nicht im Überblick dargestellt sein sollen", metavar=("path", "section"))
exclude_from_summary = parser.add_mutually_exclusive_group()
exclude_from_summary.add_argument('--rm_summary_ids_str', action="store", nargs="*", default=None, dest="excluded_summary_ids", help="Angabe aller Nummern, die von der Zusammenfassung ausgeschlossen sein sollen", metavar="id1 id2")
exclude_from_summary.add_argument('--rm_summary_ids_cfg', action="GetIDsFromCFG", nargs=2, default=None, dest="excluded_summary_ids", help="cfg-Pfad & Sektion, in der Nummern aufgelistet sind, die von der Zusammenfassung ausgeschlossen sein sollen", metavar=("path", "section"))
args = parser.parse_args()
match args.output_type:
case "excel":
excel_comparison = ExcelExport(asm_id=args.sivas_id,
asm_json_dir=args.bom_filedir,
asm_json_filename=f'{args.sivas_id}.json',
asm_csv_dir=args.teilestamm_filedir,
asm_csv_filename=f"{args.sivas_id}.csv",
rd_dbase_dir=os.path.dirname(args.rd_ids_filepath),
rd_dbase_filename=os.path.basename(args.rd_ids_filepath),
load_local_asm_json=args.local_bom,
load_local_asm_csv=args.local_teilestamm,
load_local_rd_dbase=args.local_rd_ids,
no_blue_ids=args.no_blue_ids)
excel_comparison.write_excel()
case "tree":
treeview_comparison = Treeview(asm_id=args.sivas_id,
asm_json_dir=args.bom_filedir,
asm_json_filename=f'{args.sivas_id}.json',
asm_csv_dir=args.teilestamm_filedir,
asm_csv_filename=f'{args.sivas_id}.csv',
rd_dbase_dir=os.path.dirname(args.rd_ids_filepath),
rd_dbase_filename=os.path.basename(args.rd_ids_filepath),
load_local_asm_json=args.local_bom,
load_local_asm_csv=args.local_teilestamm,
load_local_rd_dbase=args.local_rd_ids,
no_blue_ids=args.no_blue_ids,
excluded_bom_ids=args.excluded_bom_ids,
excluded_summary_ids=args.excluded_summary_ids)
treeview_comparison.generate_tree()
main()
+290 -375
View File
@@ -1,17 +1,24 @@
import os import os
from tkinter import messagebox
import update_database
from manage_configs import SivasBOM, SivasTeilestamm, RuleDesignerDatabaseConfig, MigrationStatus
""" """
Contains the logic for the MVC of CreoMigrate Gui Contains the logic for the MVC of CreoMigrate Gui
""" """
# Infos und Fehlermeldungen die ausgelöst werden können # Infos und Fehlermeldungen die ausgelöst werden können
messages = { messages = {
"pdm_kategorie_definiert": "PDM-Kategorie nicht definiert",
"rüstcode_infos": 'Bitte Rüstcode auswählen!', "rüstcode_infos": 'Bitte Rüstcode auswählen!',
"beschaffungsart_infos": ' Komponenten der Schweißbaugruppe müssen eigene Teilenummern erhalten, falls diese aktuell als Underline-Nummern in der Creo-Baugruppe vorliegen, aber keine eigenen Teilenummern in SIVAS besitzen!', "beschaffungsart_infos": ' Komponenten der Schweißbaugruppe müssen eigene Teilenummern erhalten, falls diese aktuell als Underline-Nummern in der Creo-Baugruppe vorliegen, aber keine eigenen Teilenummern in SIVAS besitzen!',
"mengeneinheit_infos":'Bitte prüfen, ob Mengeneinheit ≠ "M - Meter" korrekt ist!', "mengeneinheit_infos":'Bitte prüfen, ob Mengeneinheit ≠ "M - Meter" korrekt ist!',
"material_infos":'Werkstoffvorschlag nicht möglich, da das Material nicht in der Mappingdatei "Materialübersetzung.json" enthalten ist.\nBitte Werkstoff in dieser Datei nachfpflegen und prüfen, ob der Werkstoff in den nachfolgenden Systemen vorhanden ist:\n- RuleDesigner\n- SIVAS-Produktiv- und Schulungsdatenbank\n- Solid Edge\nWenn nicht, bitte in diesen Systemen ebenfalls nachpflegen!', "material_infos":'Werkstoffvorschlag nicht möglich, da das Material nicht in der Mappingdatei "Materialübersetzung.json" enthalten ist.\nBitte Werkstoff in dieser Datei nachfpflegen und prüfen, ob der Werkstoff in den nachfolgenden Systemen vorhanden ist:\n- RuleDesigner\n- SIVAS-Produktiv- und Schulungsdatenbank\n- Solid Edge\nWenn nicht, bitte in diesen Systemen ebenfalls nachpflegen!',
"unzulaessige_zeichen":'Unzulässige Zeichen identifiziert:\nZeichen: {Zeichentyp} -> Feld: {Feldname}', "unzulaessige_zeichen":"Unzulässige Zeichen identifiziert:\nZeichen: '{Zeichentyp}' -> Feld: '{Feldname}'",
"bezeichnung_zu_gross":'Bezeichnung besitzt mehr als 50 Zeichen. Bitte verkürzen!', "bezeichnung_zu_gross_50":'Bezeichnung besitzt mehr als 50 Zeichen. Bitte verkürzen!',
"bezeichnung_zu_gross_45":'Bezeichnung besitzt mehr als 45 Zeichen. Bitte verkürzen!',
"konflikt_ruestcode_saegeliste":'In Sivas prüfen, wieso Haken bei "Halbzeug ohne Sägeliste" trotz Rüstcode "SRC Standard Rüstcode" gesetzt ist.', "konflikt_ruestcode_saegeliste":'In Sivas prüfen, wieso Haken bei "Halbzeug ohne Sägeliste" trotz Rüstcode "SRC Standard Rüstcode" gesetzt ist.',
"teilenummre_ohne_ruestcode":'Teilenummer darf nicht ohne Rüstcode migriert werden!', "teilenummer_ohne_ruestcode":'Teilenummer darf nicht ohne Rüstcode migriert werden!',
"fertigungsart":'Fertigungsart falsch. Bitte berichtigen!', "fertigungsart":'Fertigungsart falsch. Bitte berichtigen!',
"fos_gruppe":'FOS-Gruppe falsch. Bitte berichtigen!', "fos_gruppe":'FOS-Gruppe falsch. Bitte berichtigen!',
"kalkulations_art":'Kalkulationsart falsch. Bitte berichtigen!', "kalkulations_art":'Kalkulationsart falsch. Bitte berichtigen!',
@@ -21,168 +28,199 @@ messages = {
"tos_gruppe_not_exist":'TOS-Gruppe exisitert nicht. Bitte eingetragene Gruppennummer korrigieren oder ergänzen!', "tos_gruppe_not_exist":'TOS-Gruppe exisitert nicht. Bitte eingetragene Gruppennummer korrigieren oder ergänzen!',
"dispo_not_exist":'Datensatz kann nicht ohne Dispogruppe migriert werden. Bitte nachpflegen!', "dispo_not_exist":'Datensatz kann nicht ohne Dispogruppe migriert werden. Bitte nachpflegen!',
"dispolauf_not_exist":'Datensatz kann nicht ohne Dispolaufgruppe migriert werden. Bitte nachpflegen!', "dispolauf_not_exist":'Datensatz kann nicht ohne Dispolaufgruppe migriert werden. Bitte nachpflegen!',
"teilenummer_not_exist_infos":'Ersetzte Teilenummer {Ersetzte Teilenummer} exisitert noch nicht in RuleDesigner. Migration trotzdem durchführen?', "teilenummer_not_exist_infos":"Ersetzte Teilenummer '{teilenummer}' exisitert noch nicht in RuleDesigner. Migration trotzdem durchführen?",
"ersatzteilenummer_not_exist_infos":'Ersatz-Teilenummer {Ersatz-Teilenummer} exisitert noch nicht in RuleDesigner. Migration trotzdem durchführen?', "ersatzteilenummer_not_exist_infos":"Ersatz-Teilenummer '{teilenummer}' exisitert noch nicht in RuleDesigner. Migration trotzdem durchführen?",
"werkstofftyp_not_exist":'Eingetragener Werkstofftyp exisitert nicht. Bitte korrigeren!', "hersteller": "Hersteller nicht in RuleDesigner enthalten. Bitte nachpflegen!",
"werkstofftyp_not_exist":'Eingetragener Werkstofftyp existiert nicht. Bitte korrigeren!',
"werkstoff_not_exist":'Werkstoff falsch. Bitte korrigieren!', "werkstoff_not_exist":'Werkstoff falsch. Bitte korrigieren!',
"color_not_defined":'Teilenummer kann nicht ohne festgelegte Farbe migriert werden!', "color_not_defined":'Teilenummer kann nicht ohne festgelegte Farbe migriert werden!',
"aenderungstext_too_long":'Änderungstext_weist zu viele Zeichen auf. Bitte auf 400 Zeichen verkürzen!', "aenderungstext_too_long":'Änderungstext_weist zu viele Zeichen auf. Bitte auf 400 Zeichen verkürzen!',
"missing_data":'Fehlende Angaben in der Oberfläche: {Labels}',
"sivas_db_error":'Diese Assembly existiert nicht. Eventuell ist es nur ein Teil?',
"export_sucessful":'Export der Migrationsdatei erfolgreich. Siehe {path}',
"export_not_sucessful":'Export der Migrationsdatei fehlgeschlagen. Überprüfe Schreibrechte für {path}.',
"export_not_sucessful_file_open":'Export fehlgeschlagen. Datei offen?',
"blacklist_not_exist": 'Bitte Blacklist vom Server holen',
"wrong_impftool_path": 'Pfad zur DataPrepUtility.exe nicht gefunden. Bitte Pfad unter ...\\bin\\cremig_setenv.bat prüfen.',
"too_many_logfiles":'Keine eindeutige Logdatei zum aktuellen DataPrep Prozess gefunden. Bitte löschen Sie die überflüssigen .log files',
"some_error_in_log":'Log Datei enthält einen Fehler. Bitte prüfen.',
"preparation_sucessful":'Preparation mit der Datei {path} erfolgreich',
"missing_in_blacklist":"{teilenummer} fehlt in der Blacklist, da sich in dessen Stückliste beigestellte oder dispo-inaktive Positionen befinden.\n\nBitte {teilenummer} in die Blacklist aufnehmen! \n\nDiese befindet sich in folgender Datei:\n//ruledesigner\\RDF_Daten\\Konfigurator\\CustomVaulting\\ERP_BOM.ini\n\nDanach dieses Programm erneut starten um die aktualisierte Blacklist zu laden",
"halbzeug_not_in_RDids":"Halbzeug-Teilenummer '{halbzeug_id}' fehlt in '{rdids_path}'.\n\nEntweder wurde das Halbzeug noch nicht migriert, oder der aktuelle Stand von RD_Teilenummern.csv muss geladen werden.\n\nZum Laden des aktuellen Standes von RD_Teilenummern.csv auf 'Suche' unter dem Eingabefeld der Baugruppennummer klicken und dieses Programm neu starten"
} }
# die folgende Hash ist nur für schnelleres Editieren hier # Der Beobachter
gui_data_keys = [ class Observer:
"asm_id", def __init__(self):
"teilenummer", pass
"datenbank",
"pdm_kategorie_neu", def attach(self, observable):
"neuaufbau", observable.subscribe(self)
"aus_halbzeug_neu",
"halbzeugnummer_neu", def notify(self, observable, *args, **kwargs):
"halbzeuglaenge_neu", #print(f"Got {args} {kwargs} from {observable}")
"halbzeugoberflaeche_neu", dependent_cbs = self._model.get_dependent(args[0])
"lebenszyklus_status_neu", for cb in dependent_cbs:
"bezeichnung1_sivas", "bezeichnung1_neu", model_values = self._model.callback(cb, None)
"bezeichnung2_sivas", "bezeichnung2_neu", if model_values:
"halbzeugOhneSaege_sivas", "halbzeugOhneSaege_neu", self.set_gui_dict(model_values)
"ruestcode_sivas", "ruestcode_neu", self.refresh_gui()
"fertigungsart_sivas", "fertigungsart_neu",
"allgemeintoleranz_sivas", "allgemeintoleranz_neu",
"fosGruppe_sivas", "fosGruppe_neu",
"kalkulationsart_sivas", "kalkulationsart_neu",
"beschaffungsart_sivas", "beschaffungsart_neu",
"mengeneinheit_sivas", "mengeneinheit_neu",
"halbzeug_sivas", "halbzeug_neu",
"tosgruppe_sivas", "tosgruppe_neu",
"dispogruppe_sivas", "dispogruppe_neu",
"dispolaufgruppe_sivas","dispolaufgruppe_neu",
"hersteller_sivas", "hersteller_neu",
"ersatzfuer_sivas", "ersatzfuer_neu",
"ersetztdurch_sivas", "ersetztdurch_neu",
"herstteilenr_sivas", "herstteilenr_neu",
"werkstoffdiskr_sivas",
"werkstofftyp_sivas", "werkstofftyp_neu",
"material_sivas", "material_neu",
"oberflaeche_neu",
"farbe_neu",
"version_sivas", "version_neu",
"aenderungsindex_sivas", "aenderungsindex_neu",
"aenderungstext_sivas", "aenderungstext_neu",
"freigabevermerk_sivas", "freigabevermerk_neu",
"zusatzinfos_auto_text",
"zusatzinfos_bendef_text",
# Felder der Comboboxen. benannt wie deren callbacks
"cb_pdm_kategorie_neu",
"cb_halbzeug_neu",
"cb_halbzeugoberflaeche",
"cb_halbzeugfarbe",
"cb_lebenszyklus_status_neu",
"cb_3Dmodel_neu",
"cb_halbzeugOhneSaege_neu",
"cb_ruestcode_neu",
"cb_fertigungsart_neu",
"cb_allgemeintoleranz_neu",
"cb_fosGruppe_neu",
"cb_kalkulationsart_neu",
"cb_beschaffungsart_neu",
"cb_mengeneinheit_neu",
"cb_dispogruppe_neu",
"cb_dispolaufgruppe_neu",
"cb_hersteller_neu",
"cb_werkstofftyp_neu",
"cb_material_neu",
"cb_oberflaeche_neu",
"cb_farbe_neu",
# buttons
"cb_speichern",
"cb_migrieren",
"cb_zurücksetzen",
]
class Controller():
class Controller(Observer):
""" """
Class for manipulating the model and returning data for the view Class for manipulating the model and returning data for the view
""" """
def __init__(self, model, view): def __init__(self, model, view):
self._environment = None
self._config = None
self.set_model(model) self.set_model(model)
self.set_view(view) self.set_view(view)
self.logic = None
self.env = None
def set_env(self, env): def set_env(self, env):
self.environment = env self._environment = env
def get_env(self, env_path): def get_env(self, env_path):
if self.environment == None: if self._environment == None:
raise Exception("No environment set") raise Exception("No environment set")
if env_path == "lib": if env_path == "lib":
ret = self.environment.lib_dir ret = self._environment.lib_dir
elif env_path == "data": elif env_path == "data":
ret = self.environment.data_dir ret = self._environment.data_dir
elif env_path == "out": elif env_path == "out":
ret = self.environment.out_dir ret = self._environment.out_dir
elif env_path == "cfg": elif env_path == "cfg":
ret = self.environment.cfg_dir ret = self._environment.cfg_dir
elif env_path == "log":
ret = self._environment.log_dir
elif env_path == "rd_dbase_filename":
ret = self._environment.ruledesigner_csv_filename
else: else:
raise Exception("this path is not defined "+env_path) raise Exception("this path is not defined "+env_path)
return ret return ret
def add_logic(self, logic): def set_config(self, config):
self.logic = logic self._config = config
def remove_logic(self): def get_config(self):
self.logic = None return self._config
def get_orange_ids(self, red_ids):
"""just check which files have already been worked with, so data has been added"""
orange = dict()
work = self.get_env('out')
for red in red_ids:
if os.path.exists(os.path.join(work, red +'.json')):
orange[red] = True
return orange
def get_csv_files_of_asm(self, asm_id, load_local_bom=False, load_local_teilestamm=False, load_local_rd_ids=False):
""" Holt sich die Metadaten der Stücklistenpositionen als CSV"""
data_dir = self.get_env("data")
rd_dbase_filename = self.get_env("rd_dbase_filename")
excluded_bom_ids = self._config.bom_config.get_excluded_ids("ExcludedPartnumbersInBOM") # Artikelnummern wie z.B. "MA0000006" sollen nicht im Baum dargestellt werden
sivas_bom = SivasBOM(asm_id, data_dir, asm_id + '.json', load_local_bom, excluded_bom_ids)
sivas_bom.extend_asm_bom(asm_id, {"Parent": None, "Position": "10/0"}) # Ergänzt Stücklistendaten um eine fiktive Baugruppe "None", in der die Haupt-Teilenummer als Pos. 1 vorliegt. Dadurch können auch Teilenummern ohne Stückliste korrekt abgebildet werden
rd_data = RuleDesignerDatabaseConfig(data_dir, rd_dbase_filename, load_local_rd_ids)
migration_status = MigrationStatus(sivas_bom.child_ids, rd_data.ids)
pending_ids = migration_status.ids_pending
sivas_teilestamm = SivasTeilestamm(data_dir, asm_id + '.csv', load_local_csv=load_local_teilestamm)
sivas_teilestamm.create_csvs(pending_ids)
self._model.set_red_ids(pending_ids)
self._model.set_parent_children(sivas_bom.parent_children)
self._model.set_asm_id(asm_id)
self._model.set_bom_properties(sivas_bom.all_bom_properties)
def set_model(self, model): def set_model(self, model):
self.model = model self._model = model
self.attach(model)
def set_view(self, view): def set_view(self, view):
self.view = view self._view = view
def refresh_gui(self): def refresh_gui(self):
self.view.data_from_model() self._view.data_from_model()
def data_from_model(self): self._view.set_states()
self.view.data_from_model() # def data_from_model(self):
# self._view.data_from_model()
def data_from_view(self, key=None):
return self._view.data_from_view(key)
def get_current_asm_id(self): def get_current_asm_id(self):
self.model.get_current_asm_id() self._model.get_asm_id()
def set_current_asm_id(self, asm_id): def set_current_asm_id(self, asm_id, load_local_bom=False, load_local_teilestamm=False, load_local_rd_ids=False):
self.model.set_current_asm_id(asm_id) # TODO save current given data. In case, ask whether you should save or drop
self._model.set_asm_id(asm_id)
# hole alle Daten vom Server
self.get_csv_files_of_asm(asm_id, load_local_bom, load_local_teilestamm, load_local_rd_ids)
def set_current_item_id(self, cid): def set_current_item_id(self, cid):
self.set_gui_data('teilenummer', cid) """setze eine neue Item ID """
# check before. change to given item just in case it is valid, e.g. name is a number of 9 digits
loaded_csv = self.model.sivas_data_from_csv(cid) if not cid.isnumeric():
gui_dict = self.logic.csv2guidata(loaded_csv) return
self.model.set_gui_dict(gui_dict) # nur die red-id Daten können geladen werden.
# red_ids = self._model.get_red_ids()
# if not cid in red_ids:
# return
# TODO save current given data. In case, ask whether you should save or drop
self._model.set_current_item_id(cid)
self._load_cid_data2model(cid)
def get_current_item_id(self):
return self._model.get_current_item_id()
def _load_cid_data2model(self, cid):
"""lädt alle nötigen Daten für diese ID """
# falls eine .json Datei davon im Work Ordner existiert, dann diese zuerst versuchen ins Modell zu laden
self._view.clear_rightframes()
self._model.clear()
saved_json_exists = self._model.from_json_file(self.get_env("out"), cid)
if saved_json_exists == False:
# ansonsten die .csv Datei mit den SIVAS Infos aus data holen
loaded = self._model.sivas_data_from_csv(cid)
if loaded == None:
print("no file found "+ cid)
else:
# und diese in der Gui setzen
set_data = self._model.csv2guidata(loaded)
self.set_gui_dict(set_data)
self._model.set_gui_defaults()
self.refresh_gui() self.refresh_gui()
def set_red_ids(self, red_ids): def set_red_ids(self, red_ids):
self.model.set_red_ids(red_ids) self._model.set_red_ids(red_ids)
def get_red_ids(self): def get_red_ids(self):
return self.model.get_red_ids() return self._model.get_red_ids()
def set_parent_children(self, parent_children_mapping): def set_parent_children(self, parent_children_mapping):
self.model.set_parent_children(parent_children_mapping) self._model.set_parent_children(parent_children_mapping)
def get_parent_children(self): def get_parent_children(self):
return self.model.get_parent_children() return self._model.get_parent_children()
# merkt sich die reinen Daten zum Impfen # # merkt sich die reinen Daten zum Impfen
def set_data_dict(self, data:dict): # def set_data_dict(self, data:dict):
"""merken der Daten zum Impfen""" # """merken der Daten zum Impfen"""
for k,v in data: # for k,v in data:
self.set_data(k,v) # self.set_data(k,v)
def set_data(self, key, value): # def set_data(self, key, value):
"""merken der Daten zum Impfen""" # """merken der Daten zum Impfen"""
self.model.set_data(key, value) # self._model.set_data(key, value)
def get_data(self, key): # def get_data(self, key):
return self.model.get_data(key) # return self._model.get_data(key)
def get_all_data(self): # def get_all_data(self):
return self.model.get_all_data() # return self._model.get_all_data()
# merkt sich die Nutzereingaben, bzw. Daten für die GUI # merkt sich die Nutzereingaben, bzw. Daten für die GUI
def set_gui_dict(self, data:dict): def set_gui_dict(self, data:dict):
@@ -191,274 +229,151 @@ class Controller():
self.set_gui_data(k,v) self.set_gui_data(k,v)
def set_gui_data(self, key, value): def set_gui_data(self, key, value):
"""merken der Eingaben des Nutzers der GUI """ """merken der Eingaben des Nutzers der GUI """
self.model.set_gui_data(key, value) self._model.set_gui_data(key, value)
def get_gui_data(self, key): def get_gui_data(self, key):
return self.model.get_gui_data(key) return self._model.get_gui_data(key)
def get_all_gui_data(self): def get_all_gui_data(self):
return self.model.get_all_gui_data() return self._model.get_all_gui_data()
def get_gui_states(self):
return self._model.get_states()
def get_configuration(self):
return self._model.get_configuration()
def message_info(self, title, key, values):
text = messages[key]
if 'halbzeug_id' in values:
text = text.format(halbzeug_id=values['halbzeug_id'], rdids_path=values['rdids_path'])
if 'path' in values:
text = text.format(path=values['path'])
return messagebox.showinfo(title, text)
def message_question(self, title, key, values={}):
text = messages[key]
if 'teilenummer' in values:
text = text.format(teilenummer=values['teilenummer'])
default = messagebox.NO
if 'default' in values and values['default'] == 'yes':
default = messagebox.YES
return messagebox.askquestion(title, text, type=messagebox.YESNO, default=default)
def message_error(self, title, key, values={}):
text = messages[key]
if 'Labels' in values:
text = text.format(Labels=values['Labels'])
if 'Zeichentyp' in values:
text = text.format(Zeichentyp=values['Zeichentyp'], Feldname=values['Feldname'] )
if 'path' in values:
text = text.format(path=values['path'])
if 'teilenummer' in values:
text = text.format(teilenummer=values['teilenummer'])
return messagebox.showerror(title, text)
def callback(self, key, value): def callback(self, key, value):
if not self.logic: if not self._model:
return raise Exception("no model yet added")
model_values = self.logic.callback(key, value)
if model_values: # Aktionen der Knöpfe
self.set_gui_dict(model_values) if key == 'cb_speichern':
self.refresh_gui() data = self.data_from_view()
self._model.set_gui_dict(data)
class GuiLogic(): self._model.save_to_file()
"""
Class for business logic. implementing the dependencies between different user inputs
"""
def __init__(self, model, configs):
# das Modell soll hier nur verwendet werden um aktuell Zustände abzufragen!
# alles weitere zum Setzen von Daten etc. muss über den Controller laufen, also zurück gegeben werden.
self.model = model
# hier holt man die Daten der Configs
self.config = configs
# hier sind alle Callbacks bzw. deren Comboboxen
self.callbacks = [
'cb_pdm_kategorie_neu',
'cb_neuaufbau',
'cb_aus_halbzeug_neu',
'cb_lebenszyklus_status_neu',
'cb_3Dmodel_neu',
'cb_halbzeugOhneSaege_neu',
'cb_ruestcode_neu',
'cb_fertigungsart_neu',
'cb_allgemeintoleranz_neu',
'cb_fosGruppe_neu',
'cb_kalkulationsart_neu',
'cb_beschaffungsart_neu',
'cb_mengeneinheit_neu',
'cb_halbzeug_neu',
'cb_dispogruppe_neu',
'cb_dispolaufgruppe_neu',
'cb_hersteller_neu',
'cb_werkstoffdiskrepanz',
'cb_werkstofftyp_neu',
'cb_material_neu',
'cb_oberflaeche_neu',
'cb_farbe_neu',
'cb_speichern',
'cb_migrieren',
'cb_zurücksetzen',
'cb_suche_asm'
]
# dies sind die Excel Headel der SIVAS csv Export Datei
# und wie diese in das Datenmodell der Gui integriert werden kann
self.excel_to_gui = {
"Teilenummer":"teilenummer",
"Bezeichnung1":"bezeichnung1_sivas",
"Bezeichnung2":"bezeichnung2_sivas",
"Beschaffungsart":"beschaffungsart_sivas",
"Mengeneinheit":"mengeneinheit_sivas",
"Halbzeug":"halbzeug_sivas",
"TOS_Gruppe":"tosgruppe_sivas",
"Dispogruppe":"dispolaufgruppe_sivas",
"Dispolaufgruppe":"dispolaufgruppe_sivas",
"ErsatzFuer":"ersatzfuer_neu",
"ErsetztDurch":"ersetztdurch_neu",
"AktuellerIndex":"aenderungsindex_sivas",
"Hersteller":"hersteller_sivas",
"HerstellerTeilenummer":"herstteilenr_sivas",
"Version":"version_sivas",
"HalbzeugExtern":"halbzeug_sivas",
"Werkstoff":"werkstofftyp_sivas",
"Oberfläche":"cb_oberflaeche_neu",
# "Truemmer":"truemmer",
# "HzOhneSaegeliste":"",
"Ruestcode":"ruestcode_sivas",
"Fertigungsart":"fertigungsart_sivas",
"FosGruppe":"fosGruppe_sivas",
"Kalkulationsart":"kalkulationsart_sivas",
#"Indexerfasser":"",
"Aenderungstext":"aenderungstext_sivas",
"Freigabevermerk":"freigabevermerk_sivas",
# "Indexbearbeiter":"in"
}
def csv2guidata(self, data):
ret = dict()
for k,v in data.items():
if k in self.excel_to_gui and v is not None:
ret[self.excel_to_gui[k]] = v
# Spezial: Befüllung von Änderungstext mit dem Author, falls in der .csv vorhanden
if "Indexerfasser" in data and "Aenderungstext" in data:
ret["aenderungstext_sivas"] = '{aenderungstext} (von {author})'.format(aenderungstext=data["Aenderungstext"], author=data["Indexerfasser"])
# Indexerfasser wird nicht in der gui verwaltet. Deshalb Modifikation aus den Rohdaten
# set defaults from given logic
r1 = self.callback("cb_neuaufbau", None)
ret.update(r1)
r2 = self.callback("cb_aus_halbzeug_neu", None)
ret.update(r2)
# add entry dependencies
dep = self.entry_dependencies(ret)
ret.update(dep)
return ret
def entry_dependencies(self, data):
ret = dict()
halbzeugoberflaeche = data["halbzeugoberflaeche_neu"]
if data["aus_halbzeug_neu"] == True:
if halbzeugoberflaeche == "eloxieren" or halbzeugoberflaeche == "lackieren" or halbzeugoberflaeche == "pulverbeschichten":
pass
else:
ret["halbzeugoberflaeche_neu"] = ''
else:
ret["halbzeugoberflaeche_neu"] = ''
return ret
def callback(self, key, value):
"""gibt ein dict zurück, welches neu im Modell gesetzt wird"""
if key not in self.callbacks:
raise Exception("this callback does not exist "+key)
if key == 'cb_pdm_kategorie_neu':
pass
elif key == 'cb_neuaufbau':
return self.neuaufbau(value)
elif key == 'cb_aus_halbzeug_neu':
return self.aus_halbzeug_neu(value)
elif key == 'cb_lebenszyklus_status_neu':
pass
elif key == 'cb_3Dmodel_neu':
pass
elif key == 'cb_halbzeugOhneSaege_neu':
pass
elif key == 'cb_ruestcode_neu':
pass
elif key == 'cb_fertigungsart_neu':
pass
elif key == 'cb_allgemeintoleranz_neu':
pass
elif key == 'cb_fosGruppe_neu':
pass
elif key == 'cb_kalkulationsart_neu':
pass
elif key == 'cb_beschaffungsart_neu':
pass
elif key == 'cb_mengeneinheit_neu':
pass
elif key == 'cb_halbzeug_neu':
pass
elif key == 'cb_dispogruppe_neu':
pass
elif key == 'cb_dispolaufgruppe_neu':
pass
elif key == 'cb_hersteller_neu':
pass
elif key == 'cb_werkstoffdiskrepanz':
pass
elif key == 'cb_werkstofftyp_neu':
return self.werkstofftyp(value)
elif key == 'cb_material_neu':
pass
elif key == 'cb_oberflaeche_neu':
pass
elif key == 'cb_farbe_neu':
return self.farbe(value)
elif key == 'cb_speichern':
pass
elif key == 'cb_migrieren': elif key == 'cb_migrieren':
pass data = self.data_from_view()
self._model.set_gui_dict(data)
self.migrieren()
elif key == 'cb_zurücksetzen': elif key == 'cb_zurücksetzen':
pass self.zuruecksetzen()
elif key == 'cb_suche_asm': elif key == 'cb_suche_asm':
pass # hole dir die in die GUI eingetragene Nummer
update_database.get_blacklist(self.get_env("data"))
current_asmid = self.data_from_view('asm_id')
if current_asmid != '':
self.set_current_asm_id(current_asmid)
elif key == 'cb_ladelokal_asm':
# hole dir nur die lokalen Daten. Keine Datenbankabfrage außer Blacklist
update_database.get_blacklist(self.get_env("data"))
current_asmid = self.data_from_view('asm_id')
if current_asmid != '':
self.set_current_asm_id(current_asmid, load_local_bom=True, load_local_teilestamm=True, load_local_rd_ids=True)
elif key == 'cb_3dsuchen':
self.suche_3d()
# callbacks der gui zur
else: else:
raise Exception("this callback does not exist "+key) # Logik um neue Werte in Oberfläche oder Modell zu füllen
model_values = self._model.callback(key, value)
if model_values:
self.set_gui_dict(model_values)
def neuaufbau(self, trueOrfalse): # gib dem observer Bescheid, was aufgerufen wurde
ret = dict() self.notify(self._model, key,value)
pdm_kat = self.model.get_gui_data("pdm_kategorie_neu") self.refresh_gui()
if pdm_kat != "Einzelteil" or pdm_kat != "Kaufteil":
ret["neuaufbau"] = False def migrieren(self):
return ret self._view.reset_labels()
# Pruefung ob Pflichtfelder befuellt
(ok, missing) = self._model.check_pflichtfelder()
if ok == False:
labels = ', '.join(missing)
self.message_error('Fehlende Angaben', 'missing_data', {'Labels':labels})
self._view.highlight_labels(missing)
return
# Pruefung ob assembly-id in Blacklist fehlt
update_database.get_blacklist(self.get_env("data"))
(ok, missing_blacklist_id) = self._model.check_blacklist_completeness()
if ok == False:
id = ''.join(missing_blacklist_id)
self.message_error('Fehlend in Blacklist', 'missing_in_blacklist', {'teilenummer': id})
return
# Pruefung, ob unzulaessige Zeichen vorhanden
invalid_chars = self._config.InvalidChars.get()
(ok, wrongchars) = self._model.check_improper_chars(invalid_chars)
if ok == False:
for label,achars in wrongchars.items():
chars = ''.join(achars)
self.message_error('Unzulässige Zeichen', 'unzulaessige_zeichen', {'Zeichentyp': chars, 'Feldname':label})
self._view.highlight_labels(wrongchars)
return
# Pruefung Feldinhalte
ok = self._model.check_content()
if ok == True:
data = self._model.create_migration_data()
try:
infos = self._model.create_migration_file(data)
except PermissionError:
self.message_error('export of excel', 'export_not_sucessful_file_open')
except FileExistsError:
self.message_error('export of excel', 'export_not_sucessful')
else:
self.message_info('export of excel', 'export_sucessful', {'path': infos['path']})
self._model.call_prep_tool(infos['path'])
def aus_halbzeug_neu(self, trueOrfalse):
ret = dict()
pdm_kat = self.model.get_gui_data("pdm_kategorie_neu")
if pdm_kat == "Einzelteil":
pass
else:
ret["aus_halbzeug_neu"] = False
return ret
def werkstofftyp(self, selected_werkstoff):
"""bekommt Aluminium, Stahl etc. und setzt dann die anderen Felder der Oberfläche"""
# Logik, die steuert, welcher Defaultwert gilt: def zuruecksetzen(self):
cid = self.get_current_item_id()
# In den nachfolgenden Fällen darf kein Defaultwert eingetragen self._model.clear()
# werden (selbst wenn in from_siv.csv ein Wert in der Spalte self._view.clear_rightframes()
# "Werkstoff" eingetragen sein sollte): csv_data = self._model.sivas_data_from_csv(str(cid))
# PDM-Kategorie == "Baugruppe" # transform the csv keys into keys used behind the gui
# PDM-Kategorie == "Schweissbaugruppe" gui_data = self._model.csv2guidata(csv_data)
# PDM-Kategorie == "Einzelteil" und Aus Halbzeug == True (Haken gesetzt) self.set_gui_dict(gui_data)
# create dropdown and other defaults
# Gilt PDM-Kategorie == "Kaufteil" soll der Defaultwert "siehe self._model.set_gui_defaults()
# Hersteller" eingetragen werden
# Gilt PDM-Kategorie == "Einzelteil" und Aus Halbzeug == False (kein
# Haken), dann wird der Defaultwert wie folgt bestimmt:
ret = dict()
# das Feld selbst mit dem Selektierten beschreiben
ret['werkstofftyp_neu']= selected_werkstoff
pdm_kat = self.model.get_gui_data("pdm_kategorie_neu")
aus_halbzeug = self.model.get_gui_data("aus_halbzeug_neu")
if pdm_kat == 'Einzelteil' and aus_halbzeug is False:
wnamen = self.config.Werkstoffe.get_werkstoffe_of_name(selected_werkstoff)
# setze die Inhalte der abhängigen Comboboxen neu und den Wert im Modell
ret = {
# das Feld selbst mit dem Selektierten beschreiben
'werkstofftyp_neu': selected_werkstoff,
# die neuen Inhalte der comboboxen setzen
'cb_material_neu': wnamen,
# der angezeigte Wert der Combos sollte anfangs dem ersten der Liste entsprechen
'material_neu': wnamen[0],
}
return ret
def oberfläche(self, selected):
ret = dict()
# das Feld selbst mit dem Selektierten beschreiben
ret['oberflaeche_neu']= selected
pdm_kat = self.model.get_gui_data("pdm_kategorie_neu")
aus_halbzeug = self.model.get_gui_data("aus_halbzeug_neu")
if pdm_kat == 'Einzelteil' and aus_halbzeug is False:
onamen = self.config.Oberfläche.get_oberfläche_of_type(selected)
# setze die Inhalte der abhängigen Comboboxen neu und den Wert im Modell
ret = {
# die neuen Inhalte der comboboxen setzen
'cb_oberflaeche_neu': onamen,
# der angezeigte Wert der Combos sollte anfangs dem ersten der Liste entsprechen
'oberflaeche_neu': onamen[0],
}
return ret
def farbe(self, selected):
farben_alle = self.config.Farben.get_farbauswahl()
farben_elox = self.config.Farben.get_farben_eloxieren()
# setze die Inhalte der abhängigen Comboboxen neu und den Wert im Modell
ret = {
# das Feld selbst mit dem Selektierten beschreiben
'farbe_neu': selected,
# die neuen Inhalte der comboboxen setzen
'cb_farben': farben_alle,
# der angezeigte Wert der Combos sollte anfangs dem ersten der Liste entsprechen
'farbe_neu': farben_alle[0],
}
return ret
def suche_3d(self):
pdm_kategorie_neu = self._model.get_gui_data("pdm_kategorie_neu")
aus_halbzeug = self._model.get_gui_data("aus_halbzeug_neu")
neuaufbau = self._model.get_gui_data("neuaufbau")
# Suche Knopf darf nur bei Einzelteilen funktionieren und wenn Halbzeug/NEuaufbau nicht angehakt sind
if pdm_kategorie_neu == "Einzelteil" and not (aus_halbzeug == True or neuaufbau == True):
newpath = self._view.suche_3d()
if newpath:
self._model.set_gui_data('model3d_neu', newpath)
self._model.set_gui_data('cb_3Dmodel_neu', '')
if __name__ == "__main__": if __name__ == "__main__":
-51
View File
@@ -1,51 +0,0 @@
import argparse
import os
import shutil
import subprocess
"""
Dieses Programm:
- Holt sich alle notwendigen Einzelteil-Informationen aus SIVAS in Tabellenform
"""
def get_sivas_teilestamm(sivas_id, out_dir):
sivas_id = sivas_id.strip()
sivas_teilestamm_exe = os.environ.get('SIVAS_TEILESTAMM')
if os.path.isfile(sivas_teilestamm_exe):
if os.path.isdir(out_dir):
print(f"Attempting to generate a json-file of all parts to be migrated in relation with '{sivas_id}'")
source_path = os.path.join(os.path.expandvars("%USERPROFILE%"), "AppData", "Local", "Temp", "from_siv.csv")
to_path = os.path.join(out_dir, sivas_id + ".csv")
if os.path.isfile(os.path.join(source_path)):
print("file already there. done")
exit
subprocess.run(f"{sivas_teilestamm_exe} userid=sivas password=forte database=sivas program=ExcelUeb LFDNR=500 EINSTIEG=SQL PARAMETER1={sivas_id}")
if os.path.isfile(os.path.join(source_path)):
shutil.move(source_path, to_path)
print("done")
else:
print(f"Failure - Couldn't generate {sivas_id}.json. Check for any spelling/typing errors. Otherwise given number is a part without a BOM.")
exit()
else:
print(f"'Output directory for .json-file {out_dir}' doesn't exist.")
else:
print(f"Can't execute SIVAS-database query. Check if you have established a VPN connection to the company's network and check the path of %SIVAS_DATABASE_QUERY% in cremig_setenv.bat")
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='fetches data from sivas or ruledesigner fusion', prog='update_database')
parser.add_argument('-s', '--sivasid', action='store', help='fetch data of this id from sivas fo local database folder', metavar='id')
args = parser.parse_args()
out_dir = os.environ.get('CREMIG_DATA')
if args.sivasid:
get_sivas_teilestamm(args.sivasid, out_dir)
else:
parser.print_help()
+1159 -516
View File
File diff suppressed because it is too large Load Diff
+521 -125
View File
@@ -1,21 +1,27 @@
import os import os
import json import json
from configparser import ConfigParser import pymssql
from configparser import ConfigParser
import pandas as pd import pandas as pd
import update_database
""" """
Diese Lib verwaltet alle Config dateien (als .cfg oder als .json) von CreoMigrate Diese Lib verwaltet alle Config dateien (als .cfg oder als .json) von CreoMigrate
""" """
class JsonBasedConfig: class JsonBasedConfig:
"""Klasse mit generellen Methoden für alle Config Objekte mit json files""" """Klasse mit generellen Methoden für alle Config Objekte mit json files"""
def __init__(self, config_dir, config_file): def __init__(self, config_dir: str, config_file: str):
"""merke dir den Pfad zu den Configdateien""" """merke dir den Pfad zu den Configdateien"""
self.config_path = os.path.join(config_dir, config_file) self._config_dir = config_dir
self._config_file = config_file
self._config_path = os.path.join(config_dir, config_file)
def load_json_from_file(self): def load_json_from_file(self):
"""lade das json file vom gegeben Pfad in ein json Objekt""" """lade das json file vom gegeben Pfad in ein json Objekt"""
with open(self.config_path, 'r', encoding='utf-8') as fh: with open(self._config_path, 'r', encoding='utf-8') as fh:
return json.loads(fh.read()) content = fh.read()
return json.loads(content)
def from_json(self, json_str): def from_json(self, json_str):
"""nimm den Json String zur Initialisierung des Objektes""" """nimm den Json String zur Initialisierung des Objektes"""
@@ -24,127 +30,423 @@ class JsonBasedConfig:
class CSVBasedConfig: class CSVBasedConfig:
def __init__(self, config_dir, config_file): def __init__(self, config_dir: str, config_file: str):
"""merke dir den Pfad zu den Configdateien""" """merke dir den Pfad zu den Configdateien"""
self.config_path = os.path.join(config_dir, config_file) self._config_dir = config_dir
self._config_file = config_file
self._config_path = os.path.join(config_dir, config_file)
def load_csv_from_file(self): def load_csv_from_file(self):
"""lade die csv aus dem angegebenen Dateipfad in ein Dataframe""" """lade die csv aus dem angegebenen Dateipfad in ein Dataframe"""
return pd.read_csv(self.config_path, sep=";", dtype="object") return pd.read_csv(self._config_path, sep=";", dtype="object")
class SivasAssemblyData(JsonBasedConfig): class SQLBasedConfig:
def __init__(self, server, user, pw, dbase):
self._server = server
self._user = user
self._pw = pw
self._dbase = dbase
def query_db(self, sql_statement) -> list:
"""Führt Datenbankabfrage aus und gibt Daten zurück"""
with pymssql.connect(self._server, self._user, self._pw, self._dbase) as conn:
with conn.cursor(as_dict=True) as cursor:
try:
cursor.execute(sql_statement)
except pymssql.ProgrammingError:
print("SQL-Statement konnte nicht verarbeitet werden!")
raise
ret = cursor.fetchall()
return ret
class RuleDesignerSQLData(SQLBasedConfig):
def __init__(self,
server=os.environ.get("RD_SQL_DATABASE_SERVER"),
user=os.environ.get("RD_SQL_DATABASE_USER"),
pw=os.environ.get("RD_SQL_DATABASE_PW"),
dbase=os.environ.get("RD_SQL_DATABASE_NAME")):
super().__init__(server, user, pw, dbase)
self._rd_statuses = None
@property
def rd_statuses(self) -> dict:
"""Gibt Teilenummer und zugehörigen Status zurück"""
if self._rd_statuses is None:
# Datenbankabfrage aller Teilenummern (codCodice) und der zugehörigen Status (codStatus)
sql_statement = "SELECT [codCodice] AS ID, [codStatus] AS STATUS FROM [FUSION_PDM].[dbo].[CODICI]"
sql_data = self.query_db(sql_statement)
# Jeder Teilenummer den sprechenden Stsatusnamen, statt der internen Statusnummer zuweisen
# Dafür laden der Mapping-Datei für die Statusnummern (z.B. 3 = "FREIGEGEBEN")
rd_status_cfg = IniBasedConfig(os.environ.get("CREMIG_CFG"), "RuleDesignerStatusnamen.cfg")
rd_status_sections = rd_status_cfg.sections()
rd_status_names = rd_status_cfg.get_dict(rd_status_sections[0])
self._rd_statuses = {}
for id_status_dict in sql_data:
id = id_status_dict["ID"]
status = id_status_dict["STATUS"]
self._rd_statuses[id] = rd_status_names[str(status)]
return self._rd_statuses
class SivasBOM(JsonBasedConfig):
"""Auslesen der Assembly-Informationen zu einer angegebenen Baugruppennummer""" """Auslesen der Assembly-Informationen zu einer angegebenen Baugruppennummer"""
def __init__(self, config_dir, config_file): def __init__(self,
asm_id,
config_dir: str,
config_file: str,
load_local_json=False,
excluded_ids: list=None):
super().__init__(config_dir, config_file) super().__init__(config_dir, config_file)
self.assembly_data = None
def _lazy_init_assembly_data(func): self.main_id = asm_id
"""Sorgt dafür, dass json-Datei der Baugruppe nur 1x geladen wird""" self._load_local_json = load_local_json
self.excluded_ids_by_user = excluded_ids
self._excluded_ids_in_bom = None
self._bom_data = None
self._child_ids = None
self._parent_children = None
self._longest_child_id = None
self._max_bom_depth = None
self._all_bom_properties = None
def wrapper(self, *args, **kwargs): def create_asm_json(self) -> bool:
if self.assembly_data is None: """Erstellt JSON mit den aktuellen Baugruppeninformationen"""
self.assembly_data = self.load_json_from_file()
return func(self, *args, **kwargs) if not self._load_local_json:
return wrapper update_database.get_sivas_bom(self._config_file.removesuffix(".json"))
@_lazy_init_assembly_data
def get_assembly_ids(self): @property
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 = {}
try:
self.create_asm_json()
except ValueError:
pass
try:
self._bom_data = self.load_json_from_file()
except FileNotFoundError:
pass
if self.excluded_ids_by_user is not None:
self._remove_excluded_ids_from_bom()
return self._bom_data
@property
def child_ids(self) -> set:
"""Gibt alle Teilenummern der Stückliste zurück (auch Teilenummern aus tieferen Baugruppenebenen)""" """Gibt alle Teilenummern der Stückliste zurück (auch Teilenummern aus tieferen Baugruppenebenen)"""
assembly_ids = set() if self._child_ids is None:
for child_id, parent_properties in self.assembly_data.items(): self._child_ids = set(self.bom_data.keys())
assembly_ids.add(child_id) return self._child_ids
for parent_property in parent_properties:
parent_id = parent_property["Parent"]
assembly_ids.add(parent_id)
return assembly_ids
@_lazy_init_assembly_data @property
def get_parent_children(self) -> dict: def parent_children(self) -> dict:
"""Ordnet Stücklistenpositionen (Kinder) den Baugruppennummern (Eltern) zu. Die Kinder sind entsprechend ihrer Positionsnummern in den Stücklisten sortiert.""" """Ordnet Stücklistenpositionen (Kinder) den Baugruppennummern (Eltern) zu. Die Kinder sind entsprechend ihrer Positionsnummern in den Stücklisten sortiert."""
unordered_parent_children = {} if self._parent_children is None:
unordered_parent_children = {}
for child_id, parent_properties in self.assembly_data.items(): for child_id, parent_properties in self.bom_data.items():
for parent_property in parent_properties: for parent_property in parent_properties:
parent_id = parent_property["Parent"] parent_id = parent_property["Parent"]
child_posnr_in_parent_bom = int(parent_property["Position"].lstrip(".").split("/")[0]) child_posnr_in_parent_bom = int(parent_property["Position"].lstrip(".").split("/")[0])
if parent_id not in unordered_parent_children: if parent_id not in unordered_parent_children:
unordered_parent_children[parent_id] = {} unordered_parent_children[parent_id] = {}
unordered_parent_children[parent_id][child_posnr_in_parent_bom] = child_id unordered_parent_children[parent_id][child_posnr_in_parent_bom] = child_id
ordered_parent_children = {}
for parent, children in unordered_parent_children.items():
for pos_nr, child in sorted(children.items()):
if parent not in ordered_parent_children:
ordered_parent_children[parent] = []
ordered_parent_children[parent].append(child)
self._parent_children = ordered_parent_children
return self._parent_children
def extend_asm_bom(self, id, metadata:dict) -> dict:
"""Ergänzt die Stückliste um eine weitere Teilenummer unter Berücksichtigung des vorgegebenen Formats der ausgegebenen JSON
des Programms 'Sivas2Json' von Hr. Jakob
Aktuell ist die JSON wie folgt aufgebaut:
{
"Stücklistenposition 1": [{Metadaten aus 1. SIVAS-Stammstückliste, in der die Stücklistenposition verbaut ist},
{Metadaten aus 2. SIVAS-Stammstückliste, in der die Stücklistenposition verbaut ist (falls die oberste Baugruppe weitere Unterbaugruppen enthält, in denen diese Nummer ebenfalls verbaut ist)},
...
]
"Stücklistenposition 2": [{...},
{...}
]
}"""
if id not in self.bom_data:
self._bom_data[id] = []
ordered_parent_children = {} self._bom_data[id].append(metadata)
for parent, children in unordered_parent_children.items(): return self._bom_data
for pos_nr, child in sorted(children.items()):
if parent not in ordered_parent_children:
ordered_parent_children[parent] = []
ordered_parent_children[parent].append(child)
return ordered_parent_children
def get_longest_assembly_id(self) -> str: def _remove_excluded_ids_from_bom(self) -> None:
"""Entfernt ID's aus den Stücklistendaten, die nicht enthalten sein sollen"""
# Ausgeschlossene Teilenummern, die vom User angegeben wurden, können nicht einfach aus der Stückliste entfernt werden.
# Sie müssen zunächst aufbereiten werden, denn:
# - Ausgeschlossene Nummern, die kein Bestandteil der aktuellen Baugruppe sind, sind nicht von Interesse
# - Kinder von ausgeschlossenen Teilenummern, die vom User nicht angegeben wurden sind ggf. von Interesse, müssen aber zunächst
# ermittelt werden
ids_to_remove = self.excluded_ids_in_bom
if not ids_to_remove:
return
if self.main_id in ids_to_remove:
raise ValueError(f"Haupt-Teilenummer '{self.main_id}' darf nicht ausgeschlossen sein. Bitte $CREMIG_CFG/BOM-Settings.cfg -> Sektion 'ExcludedPartnumbersInBOM' prüfen, falls diese Datei zur Definition der ausgeschlossenen Teilenummern verwendet wurde")
filtered_bom_data = {}
for id, usages in self.bom_data.items():
if id in ids_to_remove:
continue
for properties in usages:
if properties["Parent"] in ids_to_remove:
continue
if id not in filtered_bom_data:
filtered_bom_data[id] = []
filtered_bom_data[id].append(properties)
self._bom_data = filtered_bom_data
@property
def excluded_ids_in_bom(self) -> list:
""" Gibt alle Teilenummern zurück, die in der SIVAS-Stückliste vorliegen, aber davon ausgeschlossen sein sollen. """
if self._excluded_ids_in_bom is None:
excluded_ids_by_user = self.excluded_ids_by_user
to_remove = {}
for id, usages in self.bom_data.items():
# Teilenummern zunächst als ausgeschlossen anzusehen und das später zu widerrufen erleichtert die Definition der Logik
to_remove[id] = True
# Teilenummern, die vom User ausgeschlossen wurden, aber kein Bestandteil dieser Baugruppe sind, interessieren uns nicht!
if id in excluded_ids_by_user:
continue
# Kinder von ausgeschlossenen Teilenummern werden ebenfalls als ausgeschlossen betrachtet, außer sie sind Kinder von
# weiteren Teilenummern, die nicht augeschlossen sein sollen
# Hinweis:
# Für die Prüfung, ob das Kind in weiteren Teilenummern verbaut ist, würde sich die Methode "parent_children" anbieten.
# Die ist aber Lazy, sprich, wenn wir die jetzt aufrufen, arbeitet sie mit den Stücklistendaten, vor dem die Teilenummern
# entfernt wurden. Die Laziness dafür zu entfernen macht aber auch keinen Sinn, weil diese Methode bei der Erstellung von
# baumförmigen Migrationsübersichten ständig aufgerufen wird, d.h. die Performance würde darunter stark leiden!
for properties in usages:
if properties["Parent"] not in excluded_ids_by_user:
to_remove[id] = False
self._excluded_ids_in_bom = list(filter(lambda id: to_remove[id] is True, to_remove))
return self._excluded_ids_in_bom
@property
def longest_child_id(self) -> str:
"""Gibt die längste Teilenummer von allen Stücklistenpositionen zurück""" """Gibt die längste Teilenummer von allen Stücklistenpositionen zurück"""
return max(self.get_assembly_ids()) if self._longest_child_id is None:
self._longest_child_id = max(self.child_ids)
return self._longest_child_id
@_lazy_init_assembly_data @property
def get_max_bom_depth(self) -> int: def max_bom_depth(self) -> int:
"""Gibt die tiefste Stücklistenebene zurück (0 = höchste Ebene)""" """Gibt die tiefste Stücklistenebene zurück (0 = höchste Ebene)"""
bom_levels = [] if self._max_bom_depth is None:
for parents in self.assembly_data.values(): bom_levels = []
for parent in parents: for parents in self.bom_data.values():
current_bom_level = parent["Position"].count(".") for parent in parents:
bom_levels.append(current_bom_level) current_bom_level = parent["Position"].count(".")
return max(bom_levels) bom_levels.append(current_bom_level)
self._max_bom_depth = max(bom_levels)
return self._max_bom_depth
@_lazy_init_assembly_data def get_prop_val_for_single_id(self, id:str, property_name:str) -> str:
def get_property_names(self) -> list: """Gibt eine Eigenschaft von einer einzelnen Teilenummer aus der Stückliste zurück"""
"""Gibt alle Eigenschaftsnamen zurück, die in der Assembly-json-Datei enthalten sind"""
for parent_data in self.assembly_data.values(): if id not in self.bom_data:
return list(parent_data[0]) raise ValueError("Teilenummer befindet sich nicht in der Baugruppe!")
@_lazy_init_assembly_data
def get_property(self, property) -> dict:
"""Gibt eine Eigenschaft zu den Teilenummern der Stückliste zurück (z.B. Bezeichnung)"""
if property not in self.get_property_names(): if property_name not in self.bom_data[id][0]:
raise ValueError("Angegebener Eigenschaftsname exisitert nicht!") return
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)"""
id_property_mapping = {} id_property_mapping = {}
for child, parent_data in self.assembly_data.items(): for child_id, asm_usages in self.bom_data.items():
for properties in parent_data: child_properties = asm_usages[0]
id_property_mapping[child] = properties[property] id_property_mapping[child_id] = None if property_name not in child_properties else child_properties[property_name]
return id_property_mapping return id_property_mapping
@property
def all_bom_properties(self) -> dict:
"""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 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
class RuleDesignerDatabaseConfig(CSVBasedConfig): class RuleDesignerDatabaseConfig(CSVBasedConfig):
"""Auslesen der Angaben aus der RuleDesigner-Datenbank-CSV""" """Auslesen der CSV-Datei, in der alle RuleDesigner-Teilenummern aufgelistet sind"""
def __init__(self, config_dir=".", config_file="RD_Teilenummern.csv"): def __init__(self, config_dir=".", config_file="RD_Teilenummern.csv", load_local_csv=False):
super().__init__(config_dir, config_file) super().__init__(config_dir, config_file)
self._load_local_csv = load_local_csv
self._ids = None
def get_ruledesigner_ids(self): def copy_csv_from_server(self):
return tuple(self.load_csv_from_file()['Teilenummern']) """Kopiert CSV-Datei vom Server, in der alle Teilenummern, die sich in RuleDesigner befinden"""
try:
update_database.get_ruledesigner_ids()
except:
raise ValueError("CSV mit RuleDesigner-Teilenummern konnte nicht ins lokale Verzeichnis kopiert werden!")
@property
def ids(self):
if self._ids is None:
if not self._load_local_csv:
self.copy_csv_from_server()
self._ids = tuple(self.load_csv_from_file()['Teilenummern'])
return self._ids
class MigrationStatus: class MigrationStatus:
def __init__(self, file_dir, assembly_json): """Klasse gibt Informationen zum aktuellen Migrationsstand zurück, indem geprüft wird, ob die Nummern aus Sivas, auch in RuleDesigner vorliegen"""
self.sivas_assembly_data = SivasAssemblyData(file_dir, assembly_json) def __init__(self, asm_child_ids: tuple, rd_ids: tuple):
self.ruledesigner_data = RuleDesignerDatabaseConfig(file_dir) self.asm_child_ids = asm_child_ids
self.rd_ids = rd_ids
def get_migration_status(self): self._rd_statuses = None
"""Gibt zurück, ob die Teilenummern der Baugruppe bereits migriert wurden, oder nicht""" self._overview = None
sivas_assembly_ids = self.sivas_assembly_data.get_assembly_ids() self._ids_in_rd = None
ruledesigner_ids = self.ruledesigner_data.get_ruledesigner_ids() self._ids_in_progress = None
self._ids_pending = None
migration_status = {} @property
for sivas_assembly_id in sivas_assembly_ids: def id_status(self) -> dict:
migration_status[sivas_assembly_id] = True if sivas_assembly_id in ruledesigner_ids else False """Gibt zurück, ob die Stücklistenpositionen der Baugruppe migriert sind, oder nicht"""
return migration_status if self._overview is None:
self._overview = {}
for child_id in self.asm_child_ids:
self._overview[child_id] = True if child_id in self.rd_ids else False
return self._overview
@property
def ids_in_rd(self) -> list:
"""Gibt alle Stücklistenpositionen zurück, die migriert sind"""
if self._ids_in_rd is None:
self._ids_in_rd = [id for id, status in self.id_status.items() if status is True]
return self._ids_in_rd
@property
def ids_in_progress(self) -> list:
"""Gibt migrierte Stücklistenpositionen zurück, die aktuell eine Freigabe der Baugruppe verhindern, da sie sich in Arbeit befinden"""
if self._ids_in_progress is None:
rd_sql_data = RuleDesignerSQLData()
rd_statuses = rd_sql_data.rd_statuses
self._ids_in_progress = []
for id in self.ids_in_rd:
if rd_statuses[id] != "FREIGEGEBEN":
self._ids_in_progress.append(id)
return self._ids_in_progress
@property
def ids_pending(self) -> list:
"""Gibt alle Stücklistenpositionen zurück, die noch nicht migriert sind"""
if self._ids_pending is None:
self._ids_pending = [id for id, status in self.id_status.items() if status is False]
return self._ids_pending
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._data = None
def create_csvs(self, ids):
"""Erstellt CSV-Datei(en) mit den Teilestamminformationen zu der / den angegebenen Teilenummer(n)"""
if not self._load_local_csv:
update_database.get_sivas_teilestamm(ids)
@property
def teilestamm_data(self):
"""Gibt CSV-Daten als Dataframe zurück"""
if self._data is None:
self.create_csvs(self._config_file.removesuffix(".csv"))
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.teilestamm_data[property_name][0]
return ret
class TOSGroupsConfig(JsonBasedConfig): class TOSGroupsConfig(JsonBasedConfig):
@@ -169,6 +471,25 @@ class TOSGroupsConfig(JsonBasedConfig):
for cId in childIds: for cId in childIds:
self.get_children_keys(tos_hierarchy, cId, result) self.get_children_keys(tos_hierarchy, cId, result)
def get_Id2TosGroup(self):
"hole alle ids zur jeweiligen Gruppe"
# lazy. nur einmal laden, wenn noch nicht geschehen
if not self.tos_hierarchy:
self.tos_hierarchy = super().load_json_from_file()
tos_hierarchy = self.tos_hierarchy
num2refId = dict()
num2child = dict()
allkwds = self.get_all_keywords()
for kw in allkwds.keys():
refids = tos_hierarchy[kw]["reference-ids"]
for cId in refids.keys():
num2refId[cId] = refids[cId]
children = tos_hierarchy[kw]["children"]
for cId in children.keys():
num2child[cId] = children[cId]
return (num2refId, num2child)
def get_all_keywords(self): def get_all_keywords(self):
"""hole alle TOS Keywords, welche in der config Datei definiert sind""" """hole alle TOS Keywords, welche in der config Datei definiert sind"""
@@ -201,29 +522,29 @@ class MaterialTransConfig(JsonBasedConfig):
"""Auslesen der Config zu allen Materialangaben""" """Auslesen der Config zu allen Materialangaben"""
def __init__(self, config_dir='.', config_file='Materialübersetzung.json'): def __init__(self, config_dir='.', config_file='Materialübersetzung.json'):
self.materials = None self._materials = None
super().__init__(config_dir, config_file) super().__init__(config_dir, config_file)
def from_json(self, json_str): def from_json(self, json_str):
"""lade den Json String zur Initialisierung des Objektes""" """lade den Json String zur Initialisierung des Objektes"""
self.materials = super().from_json(json_str) self._materials = super().from_json(json_str)
def get_all_materials(self): def get_all_materials(self):
"""hole alle Materialien, welche in der config Datei definiert sind""" """hole alle Materialien, welche in der config Datei definiert sind"""
if not self.materials: if not self._materials:
self.materials = super().load_json_from_file() self._materials = super().load_json_from_file()
ret = list() ret = list()
for k in self.materials.keys(): for k in self._materials.keys():
ret.append(k) ret.append(k)
return ret return ret
def get_material_of_type(self, mat): def get_material_of_type(self, mat):
"""hole alle Materialien, welche in der config Datei definiert sind""" """hole alle Materialien, welche zu diesem Werkstofftyp existieren"""
if not self.materials: if not self._materials:
self.load_materials() self.load_materials()
return self.materials[mat] return self._materials[mat]
class IniBasedConfig: class IniBasedConfig:
@@ -233,39 +554,44 @@ class IniBasedConfig:
self.config_path = os.path.join(config_dir, config_file) self.config_path = os.path.join(config_dir, config_file)
if not os.path.exists(self.config_path): if not os.path.exists(self.config_path):
raise Exception("path does not exist") raise Exception("path does not exist")
self.isInitalized = False self._isInitalized = False
self.config = ConfigParser(allow_no_value=True) self._config = ConfigParser(allow_no_value=True, delimiters=("="))
self.config.optionxform = lambda option: option # preserve case for letters self._config.optionxform = lambda option: option # preserve case for letters
def from_cfg_str(self, cfg_str): def from_cfg_str(self, cfg_str):
"""nimm den config String zur Initialisierung des Objektes""" """nimm den config String zur Initialisierung des Objektes"""
self.config.read_string(cfg_str) self._config.read_string(cfg_str)
self.isInitalized = True self._isInitalized = True
def load_cfg_from_file(self): def load_cfg_from_file(self):
"""lade das config file vom gegeben Pfad""" """lade das config file vom gegeben Pfad"""
self.config.read(self.config_path, encoding='utf-8') self._config.read(self.config_path, encoding='utf-8')
self.isInitalized = True self._isInitalized = True
def get_section_options(self, section_name): def get_section_options(self, section_name):
if not self.isInitalized: if not self._isInitalized:
self.load_cfg_from_file() self.load_cfg_from_file()
return self.config.options(section_name) return self._config.options(section_name)
def sections(self): def sections(self):
if not self.isInitalized: if not self._isInitalized:
self.load_cfg_from_file() self.load_cfg_from_file()
return self.config.sections() return self._config.sections()
def get_int(self, section_name, option): def get(self, section_name, option):
if not self.isInitalized: if not self._isInitalized:
self.load_cfg_from_file() self.load_cfg_from_file()
return self.config.getint(section_name, option) return self._config.get(section_name, option)
def get_int(self, section_name, option):
if not self._isInitalized:
self.load_cfg_from_file()
return self._config.getint(section_name, option)
def get_dict(self, section_name): def get_dict(self, section_name):
if not self.isInitalized: if not self._isInitalized:
self.load_cfg_from_file() self.load_cfg_from_file()
return dict(self.config.items(section_name)) return dict(self._config.items(section_name))
class AllgemeinConfig(IniBasedConfig): class AllgemeinConfig(IniBasedConfig):
"""Auslesen der Config für alle allgemeinen Angaben""" """Auslesen der Config für alle allgemeinen Angaben"""
@@ -287,7 +613,7 @@ class BezeichnerConfig(IniBasedConfig):
def __init__(self, config_dir='.', config_file='Bezeichner.cfg'): def __init__(self, config_dir='.', config_file='Bezeichner.cfg'):
super().__init__(config_dir, config_file) super().__init__(config_dir, config_file)
def get(self): def get_all(self):
"""hole alle möglichen Bezeichner """ """hole alle möglichen Bezeichner """
return super().get_section_options("Bezeichner") return super().get_section_options("Bezeichner")
@@ -320,19 +646,19 @@ class FertigungsartConfig(IniBasedConfig):
""" """
return super().sections() return super().sections()
def get_normen_of_type(self, ftype): def get_list_in_section(self, section):
"""hole alle möglichen Oberflächen Behandlungsarten zum gegebenen Material """hole alle möglichen Oberflächen Behandlungsarten zum gegebenen Material
Allgemeintoleranz3DDruck ftype Allgemeintoleranz3DDruck ftype
-> [ISO 2768:1991-fH, ISO 2768:1991-fK, ISO 2768:1991-fL, ISO 2768:1991-mH, , ...] -> [ISO 2768:1991-fH, ISO 2768:1991-fK, ISO 2768:1991-fL, ISO 2768:1991-mH, , ...]
""" """
return super().get_section_options(ftype) return super().get_section_options(section)
class HerstellerConfig(IniBasedConfig): class HerstellerConfig(IniBasedConfig):
"""Auslesen der Config zu allen möglichen Hersteller""" """Auslesen der Config zu allen möglichen Hersteller"""
def __init__(self, config_dir='.', config_file='Hersteller.cfg'): def __init__(self, config_dir='.', config_file='Hersteller.cfg'):
super().__init__(config_dir, config_file) super().__init__(config_dir, config_file)
def get(self): def get_all(self):
"""hole alle möglichen Bezeichner """ """hole alle möglichen Bezeichner """
return super().get_section_options("Hersteller") return super().get_section_options("Hersteller")
@@ -364,6 +690,10 @@ class OberflächeConfig(IniBasedConfig):
"""hole alle Oberflächen, welche als Sektionen in der config gegeben """hole alle Oberflächen, welche als Sektionen in der config gegeben
sind, also OberflächenbehandlungStahl, OberflächenbehandlungAluminium, ... """ sind, also OberflächenbehandlungStahl, OberflächenbehandlungAluminium, ... """
return super().sections() return super().sections()
def get_oberflächen_behandlungen(self):
"""hole alle möglichen Arten von Oberflächenbehandlungen"""
return super().get_section_options('Oberflaechenbehandlungen')
def get_oberfläche_of_type(self, otype): def get_oberfläche_of_type(self, otype):
"""hole alle möglichen Oberflächen Behandlungsarten zum gegebenen Material """hole alle möglichen Oberflächen Behandlungsarten zum gegebenen Material
@@ -385,6 +715,13 @@ class WerkstoffeConfig(IniBasedConfig):
""" """
return super().get_section_options('Werkstofftyp') return super().get_section_options('Werkstofftyp')
def get_all(self):
ret = list()
l = self.get_werkstoff_namen()
for item in l:
ltemp = self.get_werkstoffe_of_name(l)
ret.append(ltemp)
return ret
def get_werkstoffe_of_name(self, wName): def get_werkstoffe_of_name(self, wName):
"""hole alle Werkstoffe unter der gegebenen Sektion """hole alle Werkstoffe unter der gegebenen Sektion
@@ -399,15 +736,59 @@ class PfadConfig(IniBasedConfig):
def __init__(self, config_dir='.', config_file='Zielpfade.cfg'): def __init__(self, config_dir='.', config_file='Zielpfade.cfg'):
super().__init__(config_dir, config_file) super().__init__(config_dir, config_file)
def get(self): class ZusatzConfig(IniBasedConfig):
"""hole alle möglichen Bezeichner """ """Auslesen der Zusatzinformationen die aus dem Änderungsindex abgeleitet werden"""
return super().get_section_options("Zielpfade") def __init__(self, config_dir='.', config_file='Zusatzinformationen.cfg'):
super().__init__(config_dir, config_file)
class InvaldCharsConfig():
"""Auslesen der Zusatzinformationen die aus dem Änderungsindex abgeleitet werden"""
def __init__(self, config_dir='.', config_file='InvalidCharacters.txt'):
self.config_path = os.path.join(config_dir, config_file)
if not os.path.exists(self.config_path):
raise Exception("path does not exist")
self._isInitalized = False
file = open(self.config_path,'r')
line = file.read()
line = line.rstrip()
self._characters = line.split(',')
def get(self):
return self._characters
class GuiConfig(IniBasedConfig):
"""Auslesen der Zusatzinformationen die aus dem Änderungsindex abgeleitet werden"""
def __init__(self, config_dir='.', config_file='gui.cfg'):
username = os.environ.get("USERNAME")
spezific_file = 'gui-' + username + '.cfg'
spezific_path = os.path.join(config_dir,spezific_file)
if os.path.exists(spezific_path):
config_file=spezific_file
super().__init__(config_dir, config_file=config_file)
class BOMConfig(IniBasedConfig):
def __init__(self, config_dir=os.environ.get("CREMIG_CFG"), config_file="BOM-Settings.cfg"):
self._config_dir = config_dir
self.config_file = config_file
super().__init__(config_dir, config_file)
@property
def config_dir(self):
return self._config_dir
@config_dir.setter
def config_dir(self, directory):
if not os.path.isdir(directory):
raise ValueError("Verzeichnis existiert nicht!")
self._config_dir = directory
def get_excluded_ids(self, section_name:str="ExcludedPartnumbersInBOM") -> tuple:
return tuple(self.get_section_options(section_name))
class Configs: class Configs:
"""Sammlung aller Configdateien """ """Sammlung aller Configdateien """
def __init__(self, cfg_dir): def __init__(self, cfg_dir):
self.cfg_dir = cfg_dir self._cfg_dir = cfg_dir
self.Allgemein = AllgemeinConfig(cfg_dir) self.Allgemein = AllgemeinConfig(cfg_dir)
self.Bezeichner = BezeichnerConfig(cfg_dir) self.Bezeichner = BezeichnerConfig(cfg_dir)
self.Farben = FarbenConfig(cfg_dir) self.Farben = FarbenConfig(cfg_dir)
@@ -417,19 +798,34 @@ class Configs:
self.Oberfläche = OberflächeConfig(cfg_dir) self.Oberfläche = OberflächeConfig(cfg_dir)
self.Pfade = PfadConfig(cfg_dir) self.Pfade = PfadConfig(cfg_dir)
self.Werkstoffe = WerkstoffeConfig(cfg_dir) self.Werkstoffe = WerkstoffeConfig(cfg_dir)
self.Zusatz = ZusatzConfig(cfg_dir)
self.InvalidChars = InvaldCharsConfig(cfg_dir)
self.Gui = GuiConfig(cfg_dir)
self.TOSGruppen = TOSGroupsConfig(cfg_dir) self.TOSGruppen = TOSGroupsConfig(cfg_dir)
self.Materialien = MaterialTransConfig(cfg_dir) self.Materialien = MaterialTransConfig(cfg_dir)
self.env = None self.bom_config = BOMConfig(cfg_dir)
self._teilenummern = None
def get_cfg_path(self): def get_cfg_path(self):
return self.cfg_dir return self._cfg_dir
def set_env(self, env): def set_data_dir(self, data_dir):
self.env = env self._data_dir = data_dir
def get_data_dir(self):
return self._data_dir
def get_env(self): def get_ruledesigner_ids(self):
if self.env: if not self._data_dir:
return self.env raise Exception("set_data_dir not called. path not set")
return None if not self._teilenummern:
self._teilenummern = RuleDesignerDatabaseConfig(self._data_dir, load_local_csv=True).ids
return self._teilenummern
def get_blacklist(self):
if not self._data_dir:
raise Exception("set_data_dir not called. path not set")
with open(os.path.join(self._data_dir, 'blacklist.txt')) as f:
lines = f.read().splitlines()
self._blacklist = lines
return self._blacklist
+9 -8
View File
@@ -1,8 +1,9 @@
numpy==1.26.1 et_xmlfile==2.0.0
pandas==2.1.1 numpy==2.2.3
python-dateutil==2.8.2 openpyxl==3.1.5
pytz==2023.3.post1 pandas==2.2.3
six==1.16.0 pymssql==2.3.2
tzdata==2023.3 python-dateutil==2.9.0.post0
et-xmlfile==1.1.0 pytz==2025.1
openpyxl==3.1.2 six==1.17.0
tzdata==2025.1
+124 -63
View File
@@ -4,102 +4,163 @@ import os
import shutil import shutil
import subprocess import subprocess
import sys import sys
import csv
""" """
Dieses Programm: Diese Library erzeugt Dateien mit RuleDesigner-, bzw. SIVAS-Informationen,
- Kopiert die CSV-Datei mit allen RuleDesigner-Nummern bzw. stellt diese durch Kopieren / Verschieben von bereits vorhandenen
- Fragt Sivas ab und generiert dabei eine json-Datei, in der alle Teilenummern aufgelistet sind, Dateien auf Netzlaufwerken bereit
die in Verbindung mit einer angegebenen Teilenummer migriert werden müssen.
""" """
def get_blacklist(outdir): def get_blacklist(outdir):
"""read out list of sivas Ids which are not allowed from network drive
'//ruledesigner//DF_Daten//onfigurator//ustomVaulting//RP_BOM.ini'
within the section 'Settings'
in the key 'PartNumbersToDrop'
""" """
Schreibt Teilenummern aus der nachfolgenden .ini-Datei in eine .txt-Datei:
-> Dateipfad: //ruledesigner/RDF_Daten/Configurator/CustomVaulting/ERP_BOM.ini'
-> Abschnitt: 'Settings'
-> Schlüssel: 'PartNumbersToDrop'
Bei diesen Teilenummern darf keine Stücklistenübergabe an SIVAS erfolgen, da sich die Stücklistenstruktur
zwischen dem CAD und SIVAS unterscheidet (vorrangig bei Baugruppen mit Lieferantenbeistellungen)
"""
blacklist_net_share = os.environ.get("BLACKLIST_DATABASE_SOURCE") blacklist_net_share = os.environ.get("BLACKLIST_DATABASE_SOURCE")
blacklist_ini_filename = os.environ.get("BLACKLIST_DATABASE_NAME") blacklist_ini_filename = os.environ.get("BLACKLIST_DATABASE_NAME")
blacklist_source_path = os.path.join(blacklist_net_share, blacklist_ini_filename) blacklist_source_path = os.path.join(blacklist_net_share, blacklist_ini_filename)
config = configparser.RawConfigParser() config = configparser.RawConfigParser()
if not os.path.isfile(blacklist_source_path):
raise FileNotFoundError(f"Kein Zugriff auf ini-Datei '{blacklist_source_path}' mit den Blacklist-Teilenummern möglich. Bitte $BLACKLIST_DATABASE_SOURCE & $BLACKLIST_DATABASE_NAME in cremig_setenv.bat sowie VPN-Verbindung prüfen")
try: try:
config.read(blacklist_source_path) config.read(blacklist_source_path)
except configparser.DuplicateOptionError: except configparser.DuplicateOptionError:
pass pass
content = config.get('Settings','PartNumbersToDrop') content = config.get('Settings','PartNumbersToDrop')
blacklist_str = content[0] # warum das als Liste erkannt wird wissen die Götter...
if len(blacklist_str) == 0 or len(content) == 0:
print(f"import of '{blacklist_ini_filename}' from '{blacklist_net_share}' failed")
exit
blacklist = blacklist_str.split(';') if isinstance(content, list):
content = content[0] # Manchmal wird String mit den Blacklist-Nummern in einer Liste geschrieben - warum wissen die Götter...
if len(content) == 0:
raise ValueError(f"Öffnen der Blacklist-Datei'{blacklist_ini_filename}' in '{blacklist_net_share}' fehlgeschlagen")
blacklist = content.split(';')
print("writing txt-file of blacklist ids...")
outfile = os.path.join(outdir, 'blacklist.txt') outfile = os.path.join(outdir, 'blacklist.txt')
print(f"Schreibe Blacklist-Teilenummern in '{outfile}'...")
with open(outfile, 'w', encoding='utf-8') as fh: with open(outfile, 'w', encoding='utf-8') as fh:
fh.write('\n'.join(blacklist)) fh.write('\n'.join(blacklist))
print("done")
def get_rd_dbase(out_dir): def get_ruledesigner_ids(out_dir=os.environ.get('CREMIG_DATA')):
"""Kopiert CSV-Datei, in der alle RuleDesigner-Teilenummern aufgelistet sind, vom Netzlaufwerk in ein lokales Verzeichnis"""
rd_csv_source_dir = os.environ.get("RD_DATABASE_SOURCE") rd_csv_source_dir = os.environ.get("RD_DATABASE_SOURCE")
rd_csv_filename = os.environ.get("RD_DATABASE_NAME") rd_csv_filename = os.environ.get("RD_DATABASE_NAME")
csv_source_path = os.path.join(rd_csv_source_dir, rd_csv_filename) csv_source_path = os.path.join(rd_csv_source_dir, rd_csv_filename)
csv_destiny_path = os.path.join(out_dir, rd_csv_filename)
if os.path.isfile(csv_source_path): if not os.path.isfile(csv_source_path):
csv_destiny_path = os.path.join(out_dir, rd_csv_filename) raise FileNotFoundError(f"CSV-Datei mit RuleDesigner-Teilenummern existiert nicht unter '{csv_source_path}'. Bitte $RD_DATABASE_SOURCE & $RD_DATABASE_NAME in cremig_setenv.bat prüfen.")
if os.path.isdir(out_dir): if not os.path.isdir(out_dir):
print("Copying CSV-file of RuleDesigner database...") raise NotADirectoryError(f"Zielverzeichnis '{out_dir}' für CSV-Datei mit RuleDesigner-Teilenummern existiert nicht. Bitte $CREMIG_DATA in cremig_setenv.bat und VPN-Verbindung prüfen")
shutil.copyfile(csv_source_path, csv_destiny_path)
print("done")
else:
print(f"Can't copy RuleDesigner-database, because output directory ${out_dir} doesn't exist. Check %CREMIG_DATA% in cremig_setenv.bat")
sys.exit(0)
else:
print(f"File with ruldesigner-partnumbers ${csv_source_path} doesn't exist. Check VPN connection and %RD_DATABASE_SOURCE% + %RD_DATABASE_NAME% in cremig_setenv.bat")
sys.exit(0)
print(f"Kopiere '{rd_csv_source_dir}\\{rd_csv_filename}'...")
shutil.copyfile(csv_source_path, csv_destiny_path)
def get_sivas_dbase(sivas_id, out_dir): def get_sivas_bom(sivas_id, out_dir=os.environ.get('CREMIG_DATA')):
sivas_exe_path = os.environ.get('SIVAS_DATABASE_QUERY') """Generiert JSON-Datei, in der die Stücklisteninformationen zu einer SIVAS-Teilenummer mit Stammstückliste gespeichert sind.
Die Erstellung der JSON-Datei erfolgt unter Verwendung des externen Sivas2Json-Programms von Hr. Jakob"""
if os.path.isfile(sivas_exe_path): sivas2json_exe_path = os.environ.get('SIVAS_BOM')
sivas_id = sivas_id.replace(".json", "")
if os.path.isdir(out_dir):
print(f"Attempting to generate a json-file of all parts to be migrated in relation with '{sivas_id}'") if not os.path.isfile(sivas2json_exe_path):
subprocess.run(f"{sivas_exe_path} -o {out_dir} --format json -number {sivas_id}") raise FileNotFoundError(f"Programmpfad '{sivas2json_exe_path}' nicht erreichbar. Bitte prüfen, ob Zugriff auf Laufwerk Y: besteht. Andernfalls $SIVAS_BOM in cremig_setenv.bat sowie VPN-Verbindung prüfen")
if os.path.isfile(os.path.join(out_dir, sivas_id + ".json")): if not os.path.isdir(out_dir):
print("done") raise NotADirectoryError(f"Ausgabeverzeichnis '{out_dir}' für die Stücklisten-JSON existiert nicht. Bitte $SIVAS_BOM in cremig_setenv.bat oder VPN-Verbindung prüfen.")
else:
print(f"Failure - Couldn't generate {sivas_id}.json. Check for any spelling/typing errors. Otherwise given number is a part without a BOM.") print(f"Erstelle JSON mit Stücklisteninformationen...")
sys.exit(0) subprocess.run(f'{sivas2json_exe_path} -o {out_dir} --format json -number "{sivas_id}"')
else:
print(f"'Output directory for .json-file {out_dir}' doesn't exist. Check cremig_setenv.bat or VPN connection.") if not os.path.isfile(os.path.join(out_dir, sivas_id + ".json")):
sys.exit(0) raise ValueError(f"{sivas_id}.json konnte nicht erzeugt werden. Evtl. Nummer ohne Stückliste.")
else:
print(f"Can't execute SIVAS-database query. Check VPN connection and check the path of %SIVAS_DATABASE_QUERY% in cremig_setenv.bat") def get_sivas_teilestamm(sivas_ids, out_dir=os.environ.get('CREMIG_DATA'), overwrite=True):
sys.exit(0)
"""
Generiert für jede angegebene SIVAS-Teilenummer eine CSV-Datei, in der die Teilestamm-Informationen gespeichert sind
Es kann eine oder mehrere Nummern angegeben werden. Mehrere Nummern sind entweder als kommaseparierter String oder
in Form einer Liste anzugeben
"""
sivas_teilestamm_exe = os.environ.get('SIVAS_TEILESTAMM')
if not os.path.isfile(sivas_teilestamm_exe):
raise FileNotFoundError(f"Programmpfad '{sivas_teilestamm_exe}' nicht erreichbar. Bitte prüfen, ob Zugriff auf Laufwerk Y: besteht. Andernfalls $SIVAS_TEILESTAMM in cremig_setenv.bat sowie VPN-Verbindung prüfen")
if not os.path.isdir(out_dir):
raise NotADirectoryError(f"Ausgabeverzeichnis '{out_dir}' für die Teilestamm-CSV existiert nicht. Bitte $SIVAS_TEILESTAMM in cremig_setenv.bat oder VPN-Verbindung prüfen.")
if isinstance(sivas_ids, str):
sivas_ids = list(set(sivas_ids.strip().split(",")))
ids_to_generate = []
for id in sivas_ids:
if not overwrite and os.path.isfile(os.path.join(out_dir, id + ".csv")):
continue
ids_to_generate.append(id)
if len(ids_to_generate) == 0:
print("CSV-Datei(en) existieren bereits oder angegebene Teilenummer(n) sind bereits migriert")
return
ids_to_generate_str = ",".join([f'"{id}"' for id in ids_to_generate]) # Anführungszeichen erforderlich, damit Art.Nr. mit Leerzeichen, z.B. "TOS Auswahl ILS" funktionieren
os.environ["SIVAS_EXCEL_EXPORT_DIR"] = out_dir # Umgebungsvariable legt Ausgabeverzeichnis der CSV-Dateien im Programm 'KSbExcelExportSivasTeilestamm' fest. Der Variablenname ist durch genanntes Programm vorgegeben, siehe help-Text des Programms!
print(f"Erstelle CSV(s) mit Teilestamminformationen...")
subprocess.run(f'{sivas_teilestamm_exe} -teilenr={ids_to_generate_str} -open_target_dir=n')
# Prüft Existenz der angegebenen SIVAS-Nummern, indem geschaut wird, ob die CSV-Dateien 2 Zeilen aufweisen
# Nicht über Returncode des Subprocess ermittelbar, da dieser immer 0 ist, auch wenn die Nr. nicht in SIVAS existiert
for id in ids_to_generate:
csv_path = os.path.join(out_dir, id + ".csv")
with open(csv_path, encoding="utf-8", newline="") as csv_file:
csv_data = csv.reader(csv_file, delimiter=";")
line_nums = sum(1 for row in csv_data)
if line_nums != 2:
raise ValueError(f"SIVAS-Teilenummer '{id}' existiert nicht! Bitte prüfen, ob Nummer korrekt geschrieben wurde!")
if __name__ == '__main__': if __name__ == '__main__':
parser = argparse.ArgumentParser(description='fetches data from sivas or ruledesigner fusion', prog='update_database')
parser.add_argument('-s', '--sivasid', action='store', help='fetch data of this id from sivas fo local database folder', metavar='id') parser = argparse.ArgumentParser(description='Erzeugt Dateien mit RuleDesigner-, bzw. SIVAS-Informationen, bzw. stellt diese bereit', prog='update_database')
parser.add_argument('-r', '--rd', action='store_true', help='fetch list of existing parts from network drive') parser.add_argument('-b', '--blacklist', action='store_true', help='Schreibe .txt-Datei mit allen Teilenummern, bei denen keine Stücklistenübergabe aus dem CAD nach SIVAS erfolgen darf')
parser.add_argument('-b', '--blacklist', action='store_true', help='fetch list of not allowed parts from network drive') parser.add_argument('-d', '--out_dir', action='store', default=os.environ.get('CREMIG_DATA'), help='Ausgabeverzeichnis für Datei', metavar="dir")
parser.add_argument('-m', '--bom', action='store_true', help='Schreibe Stückliste einer SIVAS-Teilenummer als JSON-Datei')
parser.add_argument('-o', '--overwrite', action='store_true', default=False, help='Überschreibe Datei, wenn diese bereits in Zielverzeichnis vorliegt')
parser.add_argument('-r', '--rd_ids', action='store_true' ,help='Kopiere CSV-Datei, in der alle RuleDesigner-Teilenummern aufgelistet sind')
parser.add_argument('-s', '--sivasid', action='store', help='SIVAS-Teilenummer', metavar='id')
parser.add_argument('-t', '--teilestamm', action='store_true', help='Schreibe Teilestamm-Medataten einer SIVAS-Teilenummer als CSV-Datei')
args = parser.parse_args() args = parser.parse_args()
out_dir = os.environ.get('CREMIG_DATA') if len(sys.argv) == 1:
if args.rd:
get_rd_dbase(out_dir)
elif args.sivasid:
get_sivas_dbase(args.sivasid, out_dir)
elif args.blacklist:
get_blacklist(out_dir)
else:
parser.print_help() parser.print_help()
if args.rd_ids:
get_ruledesigner_ids(args.out_dir)
if args.blacklist:
get_blacklist(args.out_dir)
if args.sivasid:
if args.teilestamm:
get_sivas_teilestamm(args.sivasid, args.out_dir, overwrite = True)
if args.bom:
get_sivas_bom(args.sivasid, args.out_dir)
Binary file not shown.