Compare commits

...

4 Commits

4 changed files with 262 additions and 79 deletions
+2 -2
View File
@@ -19,7 +19,7 @@
"program": "${file}", "program": "${file}",
"console": "integratedTerminal", "console": "integratedTerminal",
"justMyCode": true, "justMyCode": true,
"args": ["000000382", "cmd"] "args": ["-bom", "-av", "-tos", "000000382", "cmd"]
}, },
{ {
"name": "OutputAsCSV", "name": "OutputAsCSV",
@@ -28,7 +28,7 @@
"program": "${file}", "program": "${file}",
"console": "integratedTerminal", "console": "integratedTerminal",
"justMyCode": true, "justMyCode": true,
"args": ["000000382", "csv"] "args": ["-bom", "-av", "-tos", "000000382", "csv"]
} }
] ]
} }
+18 -8
View File
@@ -82,18 +82,28 @@ install.bat
### Verwendungsbeispiele ### Verwendungsbeispiele
- Ausgabe der fertigen BOM von 000000369 in Konsole: - Ausgabe der fertigen BOM von 000000369 in Konsole:
```bash ```cmd
ProcessBOM.bat 000000369 cmd ProcessBOM.bat -bom 000000369 cmd
``` ```
- Ausgabe der fertigen BOM 000000369 als CSV ins [data/out-Verzeichnis](/data/out) schreiben: - Ausgabe der fertigen BOM + AV-Workflowmeldung von 000000382 in Konsole:
```bash ```cmd
ProcessBOM.bat 000000369 csv ProcessBOM.bat -bom -av 000000382 cmd
``` ```
- Ausgabe der fertigen BOM 000000369 als CSV ins [data/out-Verzeichnis](/data/out) schreiben und automatisch öffnen: - Ausgabe der fertigen BOM + AV-Workflowmeldung + TOS-Workflowmeldung von 000000382 in Konsole:
```bash ```cmd
ProcessBOM.bat 000000369 csv -o ProcessBOM.bat -bom -av -tos 000000382 cmd
```
- Ausgabe der fertigen BOM von 000000369 als CSV ins [data/out-Verzeichnis](/data/out) schreiben:
```cmd
ProcessBOM.bat -bom 000000369 csv
```
- Ausgabe der fertigen BOM + der Nummern, die in den AV- und TOS-Workflowmeldungen enthalten sind von 000000382 als separate CSV-Dateien ins [data/out-Verzeichnis](/data/out):
```cmd
ProcessBOM.bat -bom -av -tos 000000382 csv
``` ```
### Command-Line ### Command-Line
+46 -49
View File
@@ -41,85 +41,81 @@ CREATE TABLE IF NOT EXISTS "PARTS" (
); );
CREATE TABLE IF NOT EXISTS "STKL_REGEL" ( CREATE TABLE IF NOT EXISTS "STKL_REGEL" (
"ROWID" INTEGER NOT NULL, "ROWID" INTEGER NOT NULL,
"UEBTEILENR" INTEGER, "UEBTEILENR" TEXT,
"POSNR" INTEGER, "POSNR" INTEGER,
"LFD_NR" INTEGER NOT NULL, "LFD_NR" INTEGER NOT NULL,
PRIMARY KEY("ROWID" AUTOINCREMENT), PRIMARY KEY("ROWID" AUTOINCREMENT)
CONSTRAINT "FK_COMP_POSNR" FOREIGN KEY("POSNR") REFERENCES "COMP"("POSNR"),
CONSTRAINT "FK_COMP_UEBTEILENR" FOREIGN KEY("UEBTEILENR") REFERENCES "COMP"("UEBTEILENR")
); );
CREATE TABLE IF NOT EXISTS "VAR_TEIL_BEDINGUNG_2" ( CREATE TABLE IF NOT EXISTS "VAR_TEIL_BEDINGUNG_2" (
"ROWID" INTEGER NOT NULL, "ROWID" INTEGER NOT NULL,
"UEBTEILENR" TEXT NOT NULL, "UEBTEILENR" TEXT NOT NULL,
"POSNR" INTEGER NOT NULL, "POSNR" INTEGER NOT NULL,
"UEB_LEISTEN_NR" INTEGER NOT NULL, "UEB_LEISTEN_NR" INTEGER NOT NULL,
PRIMARY KEY("ROWID" AUTOINCREMENT), PRIMARY KEY("ROWID" AUTOINCREMENT)
CONSTRAINT "FK_COMP_POSNR" FOREIGN KEY("POSNR") REFERENCES "COMP"("POSNR"),
CONSTRAINT "FK_COMP_UEBTEILENR" FOREIGN KEY("UEBTEILENR") REFERENCES "COMP"("UEBTEILENR")
); );
INSERT INTO "COMP" ("ROWID","UEBTEILENR","POSNR","KOMPTEILENR","DISPO_AKTIV_JN","MENGE","ABW_ANZAHL","LAENGE","ZUSCHNITT","RUESTCODE") VALUES (1,'000000380',10,'821096001','J',0.22,1,200.0,'20','HZS'), INSERT INTO "COMP" ("ROWID","UEBTEILENR","POSNR","KOMPTEILENR","DISPO_AKTIV_JN","MENGE","ABW_ANZAHL","LAENGE","ZUSCHNITT","RUESTCODE") VALUES (1,'000000380',10,'821096001','J',0.22,1,200.0,'20','HZS'),
(2,'000000380',20,'829416035','J',1.0,NULL,NULL,NULL,'SRC'), (2,'000000380',20,'829416035','J',1.0,NULL,NULL,NULL,'SRC'),
(3,'000000380',30,'200000168','J',1.0,NULL,NULL,NULL,'SRC'), (3,'000000380',30,'200000168','J',1.0,NULL,NULL,NULL,'SRC'),
(4,'000000380',40,'821096001','J',0.11,1,100.0,'10','HZS'), (4,'000000380',40,'821096001','J',0.11,1,100.0,'10','HZS'),
(5,'000000380',50,'821106001','J',0.23,1,200.0,'30','HZS'), (5,'000000380',50,'821106001','J',0.23,1,200.0,'30','HZS'),
(6,'000000369',10,'821106001','J',0.105,1,100.0,'5','SRC'), (6,'000000369',10,'821106001','J',0.105,1,100.0,'5','HZS'),
(7,'000000369',20,'829416035','J',1.0,NULL,NULL,NULL,'SRC'), (7,'000000369',20,'829416035','J',1.0,NULL,NULL,NULL,'SRC'),
(8,'000000369',30,'821106001','J',0.21,1,200.0,'10','SRC'), (8,'000000369',30,'821106001','J',0.21,1,200.0,'10','HZS'),
(9,'000000369',40,'822066207','J',1.0,NULL,NULL,NULL,'SRC'), (9,'000000369',40,'822066207','J',1.0,NULL,NULL,NULL,'SRC'),
(10,'000000371',10,'821106001','J',0.105,1,100.0,'5','SRC'), (10,'000000371',10,'821106001','J',0.105,1,100.0,'5','HZS'),
(11,'000000371',20,'829416035','J',1.0,NULL,NULL,NULL,'SRC'), (11,'000000371',20,'829416035','J',1.0,NULL,NULL,NULL,'SRC'),
(12,'000000371',30,'821106001','J',0.21,1,200.0,'10','SRC'), (12,'000000371',30,'821106001','J',0.21,1,200.0,'10','HZS'),
(13,'000000371',40,'822066207','J',1.0,NULL,NULL,NULL,'SRC'), (13,'000000371',40,'822066207','J',1.0,NULL,NULL,NULL,'SRC'),
(14,'000000372',10,'821106001','J',0.105,1,100.0,'5','SRC'), (14,'000000372',10,'821106001','J',0.105,1,100.0,'5','HZS'),
(15,'000000372',20,'821106001','J',0.21,1,200.0,'10','SRC'), (15,'000000372',20,'821106001','J',0.21,1,200.0,'10','HZS'),
(16,'000000372',30,'821106001','J',0.315,1,300.0,'15','SRC'), (16,'000000372',30,'821106001','J',0.315,1,300.0,'15','HZS'),
(17,'000000372',40,'822066207','J',1.0,NULL,NULL,NULL,'SRC'), (17,'000000372',40,'822066207','J',1.0,NULL,NULL,NULL,'SRC'),
(18,'000000373',10,'821106001','J',0.105,1,100.0,'5','SRC'), (18,'000000373',10,'821106001','J',0.105,1,100.0,'5','HZS'),
(19,'000000373',20,'821106001','J',0.21,1,200.0,'10','SRC'), (19,'000000373',20,'821106001','J',0.21,1,200.0,'10','HZS'),
(20,'000000373',30,'822066207','J',1.0,NULL,NULL,NULL,'SRC'), (20,'000000373',30,'822066207','J',1.0,NULL,NULL,NULL,'SRC'),
(21,'000000374',10,'821106001','J',0.105,1,100.0,'5','SRC'), (21,'000000374',10,'821106001','J',0.105,1,100.0,'5','HZS'),
(22,'000000374',20,'821106001','J',0.21,1,200.0,'10','SRC'), (22,'000000374',20,'821106001','J',0.21,1,200.0,'10','HZS'),
(23,'000000374',30,'822066207','J',1.0,NULL,NULL,NULL,'SRC'), (23,'000000374',30,'822066207','J',1.0,NULL,NULL,NULL,'SRC'),
(24,'000000374',40,'821106001','J',0.315,1,300.0,'15','SRC'), (24,'000000374',40,'821106001','J',0.315,1,300.0,'15','HZS'),
(25,'000000375',10,'821106001','J',0.105,1,100.0,'5','SRC'), (25,'000000375',10,'821106001','J',0.105,1,100.0,'5','HZS'),
(26,'000000375',20,'821106001','J',0.21,1,200.0,'10','SRC'), (26,'000000375',20,'821106001','J',0.21,1,200.0,'10','HZS'),
(27,'000000375',30,'822066207','J',1.0,NULL,NULL,NULL,'SRC'), (27,'000000375',30,'822066207','J',1.0,NULL,NULL,NULL,'SRC'),
(28,'000000375',40,'821106001','J',0.315,1,300.0,'15','SRC'), (28,'000000375',40,'821106001','J',0.315,1,300.0,'15','HZS'),
(29,'000000376',10,'821106001','J',0.105,1,100.0,'5','SRC'), (29,'000000376',10,'821106001','J',0.105,1,100.0,'5','HZS'),
(30,'000000376',20,'829416035','J',1.0,NULL,NULL,NULL,'SRC'), (30,'000000376',20,'829416035','J',1.0,NULL,NULL,NULL,'SRC'),
(31,'000000376',30,'822066207','J',1.0,NULL,NULL,NULL,'SRC'), (31,'000000376',30,'822066207','J',1.0,NULL,NULL,NULL,'SRC'),
(32,'000000377',10,'829416035','J',1.0,NULL,NULL,NULL,'SRC'), (32,'000000377',10,'829416035','J',1.0,NULL,NULL,NULL,'SRC'),
(33,'000000377',20,'822066207','J',1.0,NULL,NULL,NULL,'SRC'), (33,'000000377',20,'822066207','J',1.0,NULL,NULL,NULL,'SRC'),
(34,'000000378',10,'821106001','J',0.105,1,100.0,'5','SRC'), (34,'000000378',10,'821106001','J',0.105,1,100.0,'5','HZS'),
(35,'000000370',10,'821106001','J',0.105,1,100.0,'5','SRC'), (35,'000000370',10,'821106001','J',0.105,1,100.0,'5','HZS'),
(36,'000000379',10,'821106001','J',0.1,1,100.0,NULL,'SRC'), (36,'000000379',10,'821106001','J',0.1,1,100.0,NULL,'HZS'),
(37,'000000379',20,'829416035','J',1.0,NULL,NULL,NULL,'SRC'), (37,'000000379',20,'829416035','J',1.0,NULL,NULL,NULL,'SRC'),
(38,'000000379',30,'821106001','J',0.2,1,200.0,NULL,'SRC'), (38,'000000379',30,'821106001','J',0.2,1,200.0,NULL,'HZS'),
(39,'000000379',40,'822066207','J',1.0,NULL,NULL,NULL,'SRC'), (39,'000000379',40,'822066207','J',1.0,NULL,NULL,NULL,'SRC'),
(40,'000000381',10,'821106001','J',0.107,1,100.0,'7','SRC'), (40,'000000381',10,'829516004','J',0.107,1,100.0,'7','HZS'),
(41,'000000381',20,'829516004','J',0.207,1,200.0,'7','SRC'), (41,'000000381',20,'829516004','J',0.207,1,200.0,'7','HZS'),
(42,'000000381',30,'822066026','J',0.302,1,300.0,'2','SRC'), (42,'000000381',30,'822066026','J',0.302,1,300.0,'2','HZS'),
(43,'000000381',40,'829516004','J',0.307,1,300.0,'7','SRC'), (43,'000000381',40,'829516004','J',0.307,1,300.0,'7','HZS'),
(44,'000000381',50,'822066089','J',0.153,1,150.0,'3','SRC'), (44,'000000381',50,'822066089','J',0.153,1,150.0,'3','HZS'),
(45,'000000381',60,'829416035','J',1.0,NULL,NULL,NULL,'SRC'), (45,'000000381',60,'829416035','J',1.0,NULL,NULL,NULL,'SRC'),
(46,'000000381',70,'822066207','J',1.0,NULL,NULL,NULL,'SRC'), (46,'000000381',70,'822066207','J',1.0,NULL,NULL,NULL,'SRC'),
(47,'000000381',80,'822066089','J',0.253,1,250.0,'3','SRC'), (47,'000000381',80,'822066089','J',0.253,1,250.0,'3','HZS'),
(48,'000000382',10,'822064013','J',0.101,1,100.0,'1','SRC'), (48,'000000382',10,'822064013','J',0.101,1,100.0,'1','HZS'),
(49,'000000382',20,'829416031','J',0.205,1,200.0,'5','SRC'), (49,'000000382',20,'829416031','J',0.205,1,200.0,'5','HZS'),
(50,'000000382',30,'822066026','J',0.302,1,300.0,'2','SRC'), (50,'000000382',30,'822066026','J',0.302,1,300.0,'2','HZS'),
(51,'000000382',40,'829516001','J',0.106,1,100.0,'6','SRC'), (51,'000000382',40,'829516001','J',0.106,1,100.0,'6','HZS'),
(52,'000000382',50,'822066089','J',0.153,1,150.0,'3','SRC'), (52,'000000382',50,'822066089','J',0.153,1,150.0,'3','HZS'),
(53,'000000382',60,'827076001','J',0.104,1,100.0,'4','SRC'), (53,'000000382',60,'827076001','J',0.104,1,100.0,'4','HZS'),
(54,'000000382',70,'827076001','J',0.204,1,200.0,'4','SRC'), (54,'000000382',70,'827076001','J',0.204,1,200.0,'4','HZS'),
(55,'000000382',80,'827076001','J',0.304,1,300.0,'4','SRC'), (55,'000000382',80,'827076001','J',0.304,1,300.0,'4','HZS'),
(56,'000000382',90,'829516001','J',0.206,1,200.0,'6','SRC'), (56,'000000382',90,'829516001','J',0.206,1,200.0,'6','HZS'),
(57,'000000382',100,'822064013','J',0.201,1,200.0,'1','SRC'), (57,'000000382',100,'822064013','J',0.201,1,200.0,'1','HZS'),
(58,'000000382',110,'822066089','J',0.253,1,250.0,'3','SRC'), (58,'000000382',110,'822066089','J',0.253,1,250.0,'3','HZS'),
(59,'000000382',120,'829516004','J',0.107,1,100.0,'7','SRC'), (59,'000000382',120,'829516004','J',0.107,1,100.0,'7','HZS'),
(60,'000000382',130,'829516004','J',0.207,1,200.0,'7','SRC'), (60,'000000382',130,'829516004','J',0.207,1,200.0,'7','HZS'),
(61,'000000382',140,'829516051','J',0.208,1,200.0,'8','SRC'), (61,'000000382',140,'829516051','J',0.208,1,200.0,'8','HZS'),
(62,'000000382',150,'829516004','J',0.307,1,300.0,'7','SRC'), (62,'000000382',150,'829516004','J',0.307,1,300.0,'7','HZS'),
(63,'000000382',160,'821106001','J',0.36,1,350.0,'10','SRC'), (63,'000000382',160,'821106001','J',0.36,1,350.0,'10','HZS'),
(64,'000000382',170,'829416035','J',1.0,NULL,NULL,NULL,'SRC'), (64,'000000382',170,'829416035','J',1.0,NULL,NULL,NULL,'SRC'),
(65,'000000382',180,'822066207','J',1.0,NULL,NULL,NULL,'SRC'); (65,'000000382',180,'822066207','J',1.0,NULL,NULL,NULL,'SRC');
INSERT INTO "PARTS" ("TEILENR","BEZ","BEZ2","KZKAUF","MENGENC","ABW_ANZAHL_JN","DISPO_AKTIV_JN","GRNR","DISPO_GRUPPE","DISPOLAUF_GRUPPE","ÄnderungsIndex","HERSTELLERNAME","TEILENR_HERSTELLER","INFO2","INFO16","WERKSTOFF","OBERFLAECHE","TRUEMMER","INFO2_JN","RUESTCODE","FERTIGUNGSART","FOSGRUPPE","INFO14","INDEXERFASSER","STATUS") VALUES (200000168,'Außenspur SP-Bogen 30°',NULL,'K','Stck','N','J','6','10','20','C',NULL,NULL,NULL,NULL,'PA 6','Masterbatch (Grundfarbe)','FALSCH','N','SRC','SP','0','Eigenbau','B.MÜLLER','5'), INSERT INTO "PARTS" ("TEILENR","BEZ","BEZ2","KZKAUF","MENGENC","ABW_ANZAHL_JN","DISPO_AKTIV_JN","GRNR","DISPO_GRUPPE","DISPOLAUF_GRUPPE","ÄnderungsIndex","HERSTELLERNAME","TEILENR_HERSTELLER","INFO2","INFO16","WERKSTOFF","OBERFLAECHE","TRUEMMER","INFO2_JN","RUESTCODE","FERTIGUNGSART","FOSGRUPPE","INFO14","INDEXERFASSER","STATUS") VALUES (200000168,'Außenspur SP-Bogen 30°',NULL,'K','Stck','N','J','6','10','20','C',NULL,NULL,NULL,NULL,'PA 6','Masterbatch (Grundfarbe)','FALSCH','N','SRC','SP','0','Eigenbau','B.MÜLLER','5'),
@@ -137,6 +133,7 @@ INSERT INTO "PARTS" ("TEILENR","BEZ","BEZ2","KZKAUF","MENGENC","ABW_ANZAHL_JN","
(829516051,'GLEITPROFIL - STAHLBANDFÜHRUNG FÜR ILS 2100',NULL,'K','M','J','J','3003','10','20','A',NULL,NULL,'110309',NULL,'Murtfeldt "S" 1000','Masterbatch (Grundfarbe)','FALSCH','J','HZS','EX','0','Eigenbau','B.MÜLLER','5'), (829516051,'GLEITPROFIL - STAHLBANDFÜHRUNG FÜR ILS 2100',NULL,'K','M','J','J','3003','10','20','A',NULL,NULL,'110309',NULL,'Murtfeldt "S" 1000','Masterbatch (Grundfarbe)','FALSCH','J','HZS','EX','0','Eigenbau','B.MÜLLER','5'),
(829526000,'STRUKTUR-PROFIL',NULL,'K','M','J','J','6','10','20','A',NULL,NULL,'120214',NULL,'EN AW-6063-T66','eloxieren','FALSCH','N','HZS','SN','0','Eigenbau','S.STEUER','5'), (829526000,'STRUKTUR-PROFIL',NULL,'K','M','J','J','6','10','20','A',NULL,NULL,'120214',NULL,'EN AW-6063-T66','eloxieren','FALSCH','N','HZS','SN','0','Eigenbau','S.STEUER','5'),
(829526517,'WEICHENPLATTE R-G - ILS II',NULL,'K','Stck','N','J','6','10','20','B',NULL,NULL,NULL,NULL,'1.0038 (S235JR)','verzinken','FALSCH','N','SRC','LW','0','Eigenbau','B.MÜLLER','5'); (829526517,'WEICHENPLATTE R-G - ILS II',NULL,'K','Stck','N','J','6','10','20','B',NULL,NULL,NULL,NULL,'1.0038 (S235JR)','verzinken','FALSCH','N','SRC','LW','0','Eigenbau','B.MÜLLER','5');
INSERT INTO "STKL_REGEL" ("ROWID","UEBTEILENR","POSNR","LFD_NR") VALUES (1,'000000369',20,1);
INSERT INTO "VAR_TEIL_BEDINGUNG_2" ("ROWID","UEBTEILENR","POSNR","UEB_LEISTEN_NR") VALUES (1,'000000369',10,418), INSERT INTO "VAR_TEIL_BEDINGUNG_2" ("ROWID","UEBTEILENR","POSNR","UEB_LEISTEN_NR") VALUES (1,'000000369',10,418),
(2,'000000369',30,420), (2,'000000369',30,420),
(3,'000000370',10,419), (3,'000000370',10,419),
+196 -20
View File
@@ -2,7 +2,6 @@ import argparse
import csv import csv
import os import os
import sqlite3 import sqlite3
import subprocess
def main(): def main():
parser = argparse.ArgumentParser(description='Programm erstellt finale SIVAS-Stückliste aus der RuleDesigner-Stücklisten-CSV unter Berücksichtigung der spezifizierten Verschiebelogik!', parser = argparse.ArgumentParser(description='Programm erstellt finale SIVAS-Stückliste aus der RuleDesigner-Stücklisten-CSV unter Berücksichtigung der spezifizierten Verschiebelogik!',
@@ -12,17 +11,19 @@ def main():
parser.register("action", "store_after_check", ArgparseDirectoryCheck) parser.register("action", "store_after_check", ArgparseDirectoryCheck)
parser.register("action", "store_after_code_check", ArgparseParentcodeCheck) parser.register("action", "store_after_code_check", ArgparseParentcodeCheck)
parser.add_argument("parent_code", action="store_after_code_check", type=str, help="Teilenummer der Baugruppe") parser.add_argument("parent_code", action="store_after_code_check", type=str, help="Teilenummer der Baugruppe")
parser.add_argument("--csv_dir", action="store_after_check", default=os.environ.get("PROJECT_DATA_IN"), metavar="dir", help="Verzeichnis, aus dem die Stücklisten-CSV aus RuleDesigner eingelesen werden soll. Default: /data") parser.add_argument("-csv_dir", action="store_after_check", default=os.environ.get("PROJECT_DATA_IN"), metavar="dir", help="Verzeichnis, aus dem die Stücklisten-CSV aus RuleDesigner eingelesen werden soll. Default: /data")
parser.add_argument("-bom", action="store_true", help="Ausgabe der neuen, aufbereiteten Stückliste")
parser.add_argument("-av", action="store_true", help="Ausgabe der AV-Workflowmeldungen (falls vorhanden)")
parser.add_argument("-tos", action="store_true", help="Ausgabe der TOS-Workflowmeldungen (falls vorhanden)")
subparsers = parser.add_subparsers(title="output type", required=True, help="Legt fest, in welcher Form die Stückliste ausgegeben werden soll. cmd = In Konsole, csv = als csv-Datei", dest="output_type") subparsers = parser.add_subparsers(title="output type", required=True, help="Legt fest, in welcher Form die Stückliste ausgegeben werden soll. cmd = In Konsole, csv = als csv-Datei", dest="output_type")
sp_cmd = subparsers.add_parser("cmd", help="Ausgabe der fertig bearbeiteten Stückliste in der Konsole") sp_cmd = subparsers.add_parser("cmd", help="Ausgabe der über die Flags -bom / -av / -tos ausgewählten Elemente in der Konsole")
sp_csv = subparsers.add_parser("csv", help="Ausgabe der fertig bearbeiteten Stückliste als CSV-Datei") sp_csv = subparsers.add_parser("csv", help="Ausgabe der über die Flags -bom / -av / -tos ausgewählten Elemente als CSV-Datei(en)")
sp_csv.register("action", "store_after_check", ArgparseDirectoryCheck) sp_csv.register("action", "store_after_check", ArgparseDirectoryCheck)
sp_csv.add_argument("-v", "--verbose", action="store_true", help="Alle Spalten ausgeben") sp_csv.add_argument("-v", "--verbose", action="store_true", help="Alle Spalten ausgeben")
sp_cmd.add_argument("-v", "--verbose", action="store_true", help="Alle Spalten ausgeben") sp_cmd.add_argument("-v", "--verbose", action="store_true", help="Alle Spalten ausgeben")
sp_csv.add_argument("-od", "--out_dir", action="store_after_check", default=os.environ.get("PROJECT_DATA_OUT"), metavar="dir", help="Ausgabeverzeichnis fertigen Stücklisten-CSV") sp_csv.add_argument("-od", "--out_dir", action="store_after_check", default=os.environ.get("PROJECT_DATA_OUT"), metavar="dir", help="Ausgabeverzeichnis fertigen Stücklisten-CSV")
sp_csv.add_argument("-o", "--open_csv", action="store_true", help="CSV-Datei nach dem schreiben öffnen")
args: dict = vars(parser.parse_args()) args: dict = vars(parser.parse_args())
if os.environ.get("DB_PATH") is not None: if os.environ.get("DB_PATH") is not None:
@@ -37,6 +38,8 @@ def main():
csv_handler = CSVHandler() csv_handler = CSVHandler()
sql_handler = SQLFileHandler() sql_handler = SQLFileHandler()
bom_processing = BOMProcessing(db, args["parent_code"]) bom_processing = BOMProcessing(db, args["parent_code"])
av_workflow_msg = AVWorkflowMessage(db, args["parent_code"])
tos_workflow_msg = TOSWorkflowMessage(db, args["parent_code"])
# SIVAS "nachbauen" # SIVAS "nachbauen"
sql_source_filename = "sivas_replika.sql" sql_source_filename = "sivas_replika.sql"
@@ -48,29 +51,59 @@ def main():
new_bom.create_tmp_table() new_bom.create_tmp_table()
new_bom.insert_csv_data(csv_data) new_bom.insert_csv_data(csv_data)
# Positionen für AV- bzw. TOS-Workflowmeldungen generieren (muss vor dem Schreiben der neuen Stücklist erfolgen!)
av_workflow_msg.get_av_workflow_posnrs_and_codes()
tos_workflow_msg.get_tos_workflow_posnrs_and_codes()
# Neue Stückliste erstellen / schreiben # Neue Stückliste erstellen / schreiben
bom_processing.write_new_bom() bom_processing.write_new_bom()
# Ausgabe in Konsole
if args["output_type"] == "cmd": if args["output_type"] == "cmd":
if args["verbose"]:
output = repr(new_bom)
print(output)
else:
print(new_bom)
if args["bom"]:
if args["verbose"]:
print(repr(new_bom))
else:
print(new_bom)
if args["av"]:
print(av_workflow_msg)
if args["tos"]:
print(tos_workflow_msg)
# Ausgabe als CSV-Datei(en)
elif args["output_type"] == "csv": elif args["output_type"] == "csv":
if args["verbose"]:
bom_data = new_bom.get_verbose_data()
else:
bom_data = new_bom.get_compact_data()
filedir = args["out_dir"] filedir = args["out_dir"]
filename = f"BOM_{args["parent_code"]}_final.csv" filenames = []
filepath = os.path.join(filedir, filename) file_data = []
csv_handler.write_from_dict(data=bom_data, filedir=filedir, filename=filename)
if args["open_csv"]: # CSV-Ausgabe der aufbereiteten Stückliste
subprocess.run(['cmd', '/c', 'start', '', filepath], shell=True) if args["bom"]:
if args["verbose"]:
bom_data = new_bom.get_verbose_data()
else:
bom_data = new_bom.get_compact_data()
filenames.append(f"BOM_{args["parent_code"]}_new.csv")
file_data.append(bom_data)
# CSV-Ausgabe der Positionsnummern aus der alten Stückliste, die Bestandteil der AV-Workflowmeldung sind
if args["av"]:
msg_data = av_workflow_msg.get_data()
filenames.append(f"AV_{args["parent_code"]}.csv")
file_data.append(msg_data)
# CSV-Ausgabe der Positionsnummern aus der alten Stückliste, die Bestandteil der TOS-Workflowmeldung sind
if args["tos"]:
msg_data = tos_workflow_msg.get_data()
filenames.append(f"TOS_{args["parent_code"]}.csv")
file_data.append(msg_data)
for name, data in zip(filenames, file_data):
csv_handler.write_from_dict(data=data, filedir=filedir, filename=name)
else: else:
NotImplementedError NotImplementedError
@@ -828,5 +861,148 @@ class BOMProcessing:
self.insert() self.insert()
self.update() self.update()
self.drop_tmp_tables() self.drop_tmp_tables()
class AVWorkflowMessage:
def __init__(self, db: Database, parent_code: str):
self.db = db
self.parent_code = parent_code
def __str__(self):
res = self.get_data()
msg = self._create_msg(res)
return msg
def drop_tmp_table(self):
self.db.con.execute("DROP TABLE TMP_AV_WORKFLOW_MESSAGE")
def get_av_workflow_posnrs_and_codes(self):
"""
Wenn Positionsnummern folgende Kriterien erfüllen, sollen Sie in einer Workflowmeldung an die AV-Verantwortlichen ausgegeben werden:
Kriterien:
WENN die Positionen zu einer längenabhängigen Teilenummer MIT Sägeliste gehören (d.h. Haken bei 'Halbzeug ohne Sägeliste' im Teilestamm ist nicht gesetzt)
UND diese längenabhängige Teilenummer in der alten und der neuen Stückliste vertreten ist
UND die Länge-Teilenummer-Kombination dieser Positionsnummer nur in der alten Stückliste vorliegt (aber nicht in der Neuen)
UND bei der Position mindestens eine der nachfolgenden Kriterien erfüllt ist:
- der Wert in der Spalte 'Rüstcode' weicht vom Rüstcode-Wert ab, den die zugehörige Teilenummer im Teilstamm aufweist
- in der Spalte 'Dispoaktiv' liegt kein Haken vor
- in der Spalte 'Zuschnitt' ist ein Wert definiert
"""
self.db.con.execute("DROP TABLE IF EXISTS TMP_AV_WORKFLOW_MESSAGE")
self.db.con.execute("""
CREATE TABLE TMP_AV_WORKFLOW_MESSAGE (POSNR INTEGER,
KOMPTEILENR TEXT)
""")
test = self.db.con.execute("""
--längenabhängige Teilenummern ermitteln, die in beiden Stücklisten vorliegen
WITH laengenabh_codes_in_both_boms AS (
SELECT DISTINCT ChildCode
FROM RD_COMP
WHERE ParentCode = :parent_code
AND ChildCode in (
SELECT DISTINCT KOMPTEILENR
FROM COMP
WHERE UEBTEILENR = :parent_code
AND COALESCE(LAENGE, 0) != 0
)
)
INSERT INTO TMP_AV_WORKFLOW_MESSAGE (POSNR, KOMPTEILENR)
SELECT C.POSNR, C.KOMPTEILENR
FROM COMP C
LEFT JOIN RD_COMP RD
ON C.UEBTEILENR = RD.ParentCode
AND C.KOMPTEILENR = RD.ChildCode
AND COALESCE(C.LAENGE, 0) = RD.Uebergabelaenge
INNER JOIN PARTS P
ON C.KOMPTEILENR = P.TEILENR
WHERE C.UEBTEILENR = :parent_code
AND C.KOMPTEILENR IN laengenabh_codes_in_both_boms -- Nur längenabhängige Teilenummern berücksichtigen, die in beiden Stücklisten vorliegen
AND RD.ParentCode IS NULL -- Nur Positionen berücksichtigen, deren Länge ausschließlich in der alten Stückliste vorliegt
AND P.INFO2_JN = "N" -- Nur Positionen berücksichtigen, deren zugehörige Teilenummer keinen Haken bei "Halbzeug ohne Sägeliste" im Teilestamm aufweist
AND ( -- Nur Positionen berücksichtigen, auf die min. eines der nachfolgenden Kriterien zutrifft:
C.ZUSCHNITT IS NOT NULL -- Zuschnittswert liegt vor
OR C.RUESTCODE != P.RUESTCODE -- Rüstcode der Position in der Stammstückliste ist abweichend zum Rüstcode der zugehörigen Teilenummer im Teilestamm
OR C.DISPO_AKTIV_JN = "N" -- Stücklistenpositionen besitzt keinen Haken in der Spalte "Dispoaktiv"
)
ORDER BY C.POSNR
""", {"parent_code": self.parent_code}).fetchall()
return test
def get_data(self) -> list[dict[str]]:
res = self.db.con.execute("SELECT POSNR, KOMPTEILENR FROM TMP_AV_WORKFLOW_MESSAGE").fetchall()
return res
def _create_msg(self, data: list[dict[str]] | None) -> str:
if not data:
return "\nAV-Meldung:\nKeine"
affected_positions_str = ", ".join([f"{pos["POSNR"]} - {pos["KOMPTEILENR"]}" for pos in data])
return f"\nAV-Meldung:\nBitte Stückliste {self.parent_code} prüfen. Vor der Änderung lagen bei folgenden Positionen manuelle Eintragungen / Änderungen in den Spalten „Zuschnitt“, „Rüstcode“ oder „Dispoaktiv“ vor: {affected_positions_str}"
class TOSWorkflowMessage:
def __init__(self, db: Database, parent_code: str):
self.db = db
self.parent_code = parent_code
def __str__(self):
res = self.get_data()
msg = self._create_msg(res)
return msg
def drop_tmp_table(self):
self.db.con.execute("DROP TABLE TMP_TOS_WORKFLOW_MESSAGE")
def get_tos_workflow_posnrs_and_codes(self) -> None:
"""
Wenn Positionsnummern in der Stückliste TOS-Regeln oder -Bedingungen aufweisen,
sollen Sie in einer Workflowmeldung an die TOS-Verantwortlichen ausgegeben werden.
"""
self.db.con.execute("DROP TABLE IF EXISTS TMP_TOS_WORKFLOW_MESSAGE")
self.db.con.execute("""
CREATE TABLE TMP_TOS_WORKFLOW_MESSAGE (POSNR INTEGER,
KOMPTEILENR TEXT)
""")
self.db.con.execute("""
INSERT INTO TMP_TOS_WORKFLOW_MESSAGE (POSNR, KOMPTEILENR)
SELECT C.POSNR, C.KOMPTEILENR
FROM COMP C
LEFT JOIN VAR_TEIL_BEDINGUNG_2 B
ON C.UEBTEILENR = B.UEBTEILENR
AND C.POSNR = B.POSNR
LEFT JOIN STKL_REGEL R
ON C.UEBTEILENR = R.UEBTEILENR
AND C.POSNR = R.POSNR
WHERE C.UEBTEILENR = :parent_code
AND (
B.UEB_LEISTEN_NR IS NOT NULL
OR R.LFD_NR IS NOT NULL
)
ORDER BY C.POSNR
""", {"parent_code": self.parent_code})
def get_data(self) -> list[dict[str]]:
res = self.db.con.execute("SELECT POSNR, KOMPTEILENR FROM TMP_TOS_WORKFLOW_MESSAGE").fetchall()
return res
def _create_msg(self, data: list[dict[str]] | None) -> str:
if not data:
return "\nTOS-Meldung:\nKeine"
affected_positions_str = ", ".join([f"{pos["POSNR"]} - {pos["KOMPTEILENR"]}" for pos in data])
return f"\nTOS-Meldung:\nBitte Stückliste {self.parent_code} prüfen. Vor der Änderung lagen bei folgenden Positionen TOS-Bedingungen vor: {affected_positions_str}"
if __name__ == "__main__": if __name__ == "__main__":
main() main()