Compare commits

..

7 Commits

Author SHA1 Message Date
s.steuer 1f82de5735 Testdatenbank für Programm 'DB Browser for SQLite' ergänzt (Mit diesem Programm wurden die SQL-Abfragen des Algorithmus gebaut) 2025-09-05 21:33:01 +02:00
s.steuer 5c8ca3e366 FIX - Bei der Freigabe von migrierten Baugruppen, bei denen keine Stückliste im Datensatz hinterlegt ist wird eine BOM_[...].csv ausgegeben, bei der in der Spalte 'Positionsnummer' keine Werte hinterlegt sind. Solche Stücklisten wurden fälschlicherweise eingelesen und von der Schnittstelle so interpretiert, als wären es komplett leere Stücklisten. Folglich wurden alle Positionsnummern aus der SIVAS-Stammstücklist entfernt. Dieses Problem wurde behoben. 2025-09-05 14:36:18 +02:00
s.steuer 4ece42825e Finalen Stand des Workflow 96 (Stand 250902) von Hr. Jakob ergänzt 2025-09-02 15:45:47 +02:00
s.steuer 2668eb89f8 Konfigurationen an geänderte Schalter in process_bom (siehe Commit 8826b2e) angeglichen. 2025-08-23 00:10:50 +02:00
s.steuer eaec4f591a Sektion 'Verwendung' an Argparse-Änderungen in process_bom (siehe Commit 8826b2e) angeglichen. 2025-08-23 00:08:52 +02:00
s.steuer 8826b2e132 Klasse 'AVWorkflowMessage' für die Bestimmung und Generierung der Workflowmeldung an die AV-Verantwortlichen implementiert / Klasse 'TOSWorkflowMessage' / Argparse-Schalter angepasst, sodass die AV-, bzw. TOS-Workflowmeldungen in der Konsole, oder als CSV-Dateien ausgegeben werden können. Schalter '-open_csv' entfernt, da nun ggf. auch mehrere CSV's gleichzeitig ausgegeben werden (für die Stückliste, für die Nummern der TOS-Meldung und die Nummern der AV-Meldung) 2025-08-23 00:06:32 +02:00
s.steuer f63f5c8332 Default-Rüstcodes in COMP an Teilestamm angeglichen + Foreign-Keys entfernt, da nicht benötigt 2025-08-23 00:02:32 +02:00
7 changed files with 4722 additions and 79 deletions
+2 -2
View File
@@ -19,7 +19,7 @@
"program": "${file}",
"console": "integratedTerminal",
"justMyCode": true,
"args": ["000000382", "cmd"]
"args": ["-bom", "-av", "-tos", "000000382", "cmd"]
},
{
"name": "OutputAsCSV",
@@ -28,7 +28,7 @@
"program": "${file}",
"console": "integratedTerminal",
"justMyCode": true,
"args": ["000000382", "csv"]
"args": ["-bom", "-av", "-tos", "000000382", "csv"]
}
]
}
+18 -8
View File
@@ -82,18 +82,28 @@ install.bat
### Verwendungsbeispiele
- Ausgabe der fertigen BOM von 000000369 in Konsole:
```bash
ProcessBOM.bat 000000369 cmd
```cmd
ProcessBOM.bat -bom 000000369 cmd
```
- Ausgabe der fertigen BOM 000000369 als CSV ins [data/out-Verzeichnis](/data/out) schreiben:
```bash
ProcessBOM.bat 000000369 csv
- Ausgabe der fertigen BOM + AV-Workflowmeldung von 000000382 in Konsole:
```cmd
ProcessBOM.bat -bom -av 000000382 cmd
```
- Ausgabe der fertigen BOM 000000369 als CSV ins [data/out-Verzeichnis](/data/out) schreiben und automatisch öffnen:
```bash
ProcessBOM.bat 000000369 csv -o
- Ausgabe der fertigen BOM + AV-Workflowmeldung + TOS-Workflowmeldung von 000000382 in Konsole:
```cmd
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
+46 -49
View File
@@ -41,85 +41,81 @@ CREATE TABLE IF NOT EXISTS "PARTS" (
);
CREATE TABLE IF NOT EXISTS "STKL_REGEL" (
"ROWID" INTEGER NOT NULL,
"UEBTEILENR" INTEGER,
"UEBTEILENR" TEXT,
"POSNR" INTEGER,
"LFD_NR" INTEGER NOT NULL,
PRIMARY KEY("ROWID" AUTOINCREMENT),
CONSTRAINT "FK_COMP_POSNR" FOREIGN KEY("POSNR") REFERENCES "COMP"("POSNR"),
CONSTRAINT "FK_COMP_UEBTEILENR" FOREIGN KEY("UEBTEILENR") REFERENCES "COMP"("UEBTEILENR")
PRIMARY KEY("ROWID" AUTOINCREMENT)
);
CREATE TABLE IF NOT EXISTS "VAR_TEIL_BEDINGUNG_2" (
"ROWID" INTEGER NOT NULL,
"UEBTEILENR" TEXT NOT NULL,
"POSNR" INTEGER NOT NULL,
"UEB_LEISTEN_NR" INTEGER NOT NULL,
PRIMARY KEY("ROWID" AUTOINCREMENT),
CONSTRAINT "FK_COMP_POSNR" FOREIGN KEY("POSNR") REFERENCES "COMP"("POSNR"),
CONSTRAINT "FK_COMP_UEBTEILENR" FOREIGN KEY("UEBTEILENR") REFERENCES "COMP"("UEBTEILENR")
PRIMARY KEY("ROWID" AUTOINCREMENT)
);
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'),
(3,'000000380',30,'200000168','J',1.0,NULL,NULL,NULL,'SRC'),
(4,'000000380',40,'821096001','J',0.11,1,100.0,'10','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'),
(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'),
(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'),
(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'),
(14,'000000372',10,'821106001','J',0.105,1,100.0,'5','SRC'),
(15,'000000372',20,'821106001','J',0.21,1,200.0,'10','SRC'),
(16,'000000372',30,'821106001','J',0.315,1,300.0,'15','SRC'),
(14,'000000372',10,'821106001','J',0.105,1,100.0,'5','HZS'),
(15,'000000372',20,'821106001','J',0.21,1,200.0,'10','HZS'),
(16,'000000372',30,'821106001','J',0.315,1,300.0,'15','HZS'),
(17,'000000372',40,'822066207','J',1.0,NULL,NULL,NULL,'SRC'),
(18,'000000373',10,'821106001','J',0.105,1,100.0,'5','SRC'),
(19,'000000373',20,'821106001','J',0.21,1,200.0,'10','SRC'),
(18,'000000373',10,'821106001','J',0.105,1,100.0,'5','HZS'),
(19,'000000373',20,'821106001','J',0.21,1,200.0,'10','HZS'),
(20,'000000373',30,'822066207','J',1.0,NULL,NULL,NULL,'SRC'),
(21,'000000374',10,'821106001','J',0.105,1,100.0,'5','SRC'),
(22,'000000374',20,'821106001','J',0.21,1,200.0,'10','SRC'),
(21,'000000374',10,'821106001','J',0.105,1,100.0,'5','HZS'),
(22,'000000374',20,'821106001','J',0.21,1,200.0,'10','HZS'),
(23,'000000374',30,'822066207','J',1.0,NULL,NULL,NULL,'SRC'),
(24,'000000374',40,'821106001','J',0.315,1,300.0,'15','SRC'),
(25,'000000375',10,'821106001','J',0.105,1,100.0,'5','SRC'),
(26,'000000375',20,'821106001','J',0.21,1,200.0,'10','SRC'),
(24,'000000374',40,'821106001','J',0.315,1,300.0,'15','HZS'),
(25,'000000375',10,'821106001','J',0.105,1,100.0,'5','HZS'),
(26,'000000375',20,'821106001','J',0.21,1,200.0,'10','HZS'),
(27,'000000375',30,'822066207','J',1.0,NULL,NULL,NULL,'SRC'),
(28,'000000375',40,'821106001','J',0.315,1,300.0,'15','SRC'),
(29,'000000376',10,'821106001','J',0.105,1,100.0,'5','SRC'),
(28,'000000375',40,'821106001','J',0.315,1,300.0,'15','HZS'),
(29,'000000376',10,'821106001','J',0.105,1,100.0,'5','HZS'),
(30,'000000376',20,'829416035','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'),
(33,'000000377',20,'822066207','J',1.0,NULL,NULL,NULL,'SRC'),
(34,'000000378',10,'821106001','J',0.105,1,100.0,'5','SRC'),
(35,'000000370',10,'821106001','J',0.105,1,100.0,'5','SRC'),
(36,'000000379',10,'821106001','J',0.1,1,100.0,NULL,'SRC'),
(34,'000000378',10,'821106001','J',0.105,1,100.0,'5','HZS'),
(35,'000000370',10,'821106001','J',0.105,1,100.0,'5','HZS'),
(36,'000000379',10,'821106001','J',0.1,1,100.0,NULL,'HZS'),
(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'),
(40,'000000381',10,'821106001','J',0.107,1,100.0,'7','SRC'),
(41,'000000381',20,'829516004','J',0.207,1,200.0,'7','SRC'),
(42,'000000381',30,'822066026','J',0.302,1,300.0,'2','SRC'),
(43,'000000381',40,'829516004','J',0.307,1,300.0,'7','SRC'),
(44,'000000381',50,'822066089','J',0.153,1,150.0,'3','SRC'),
(40,'000000381',10,'829516004','J',0.107,1,100.0,'7','HZS'),
(41,'000000381',20,'829516004','J',0.207,1,200.0,'7','HZS'),
(42,'000000381',30,'822066026','J',0.302,1,300.0,'2','HZS'),
(43,'000000381',40,'829516004','J',0.307,1,300.0,'7','HZS'),
(44,'000000381',50,'822066089','J',0.153,1,150.0,'3','HZS'),
(45,'000000381',60,'829416035','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'),
(48,'000000382',10,'822064013','J',0.101,1,100.0,'1','SRC'),
(49,'000000382',20,'829416031','J',0.205,1,200.0,'5','SRC'),
(50,'000000382',30,'822066026','J',0.302,1,300.0,'2','SRC'),
(51,'000000382',40,'829516001','J',0.106,1,100.0,'6','SRC'),
(52,'000000382',50,'822066089','J',0.153,1,150.0,'3','SRC'),
(53,'000000382',60,'827076001','J',0.104,1,100.0,'4','SRC'),
(54,'000000382',70,'827076001','J',0.204,1,200.0,'4','SRC'),
(55,'000000382',80,'827076001','J',0.304,1,300.0,'4','SRC'),
(56,'000000382',90,'829516001','J',0.206,1,200.0,'6','SRC'),
(57,'000000382',100,'822064013','J',0.201,1,200.0,'1','SRC'),
(58,'000000382',110,'822066089','J',0.253,1,250.0,'3','SRC'),
(59,'000000382',120,'829516004','J',0.107,1,100.0,'7','SRC'),
(60,'000000382',130,'829516004','J',0.207,1,200.0,'7','SRC'),
(61,'000000382',140,'829516051','J',0.208,1,200.0,'8','SRC'),
(62,'000000382',150,'829516004','J',0.307,1,300.0,'7','SRC'),
(63,'000000382',160,'821106001','J',0.36,1,350.0,'10','SRC'),
(47,'000000381',80,'822066089','J',0.253,1,250.0,'3','HZS'),
(48,'000000382',10,'822064013','J',0.101,1,100.0,'1','HZS'),
(49,'000000382',20,'829416031','J',0.205,1,200.0,'5','HZS'),
(50,'000000382',30,'822066026','J',0.302,1,300.0,'2','HZS'),
(51,'000000382',40,'829516001','J',0.106,1,100.0,'6','HZS'),
(52,'000000382',50,'822066089','J',0.153,1,150.0,'3','HZS'),
(53,'000000382',60,'827076001','J',0.104,1,100.0,'4','HZS'),
(54,'000000382',70,'827076001','J',0.204,1,200.0,'4','HZS'),
(55,'000000382',80,'827076001','J',0.304,1,300.0,'4','HZS'),
(56,'000000382',90,'829516001','J',0.206,1,200.0,'6','HZS'),
(57,'000000382',100,'822064013','J',0.201,1,200.0,'1','HZS'),
(58,'000000382',110,'822066089','J',0.253,1,250.0,'3','HZS'),
(59,'000000382',120,'829516004','J',0.107,1,100.0,'7','HZS'),
(60,'000000382',130,'829516004','J',0.207,1,200.0,'7','HZS'),
(61,'000000382',140,'829516051','J',0.208,1,200.0,'8','HZS'),
(62,'000000382',150,'829516004','J',0.307,1,300.0,'7','HZS'),
(63,'000000382',160,'821106001','J',0.36,1,350.0,'10','HZS'),
(64,'000000382',170,'829416035','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'),
@@ -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'),
(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');
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),
(2,'000000369',30,420),
(3,'000000370',10,419),
File diff suppressed because it is too large Load Diff
+196 -20
View File
@@ -2,7 +2,6 @@ import argparse
import csv
import os
import sqlite3
import subprocess
def main():
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_code_check", ArgparseParentcodeCheck)
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")
sp_cmd = subparsers.add_parser("cmd", help="Ausgabe der fertig bearbeiteten Stückliste in der Konsole")
sp_csv = subparsers.add_parser("csv", help="Ausgabe der fertig bearbeiteten Stückliste als CSV-Datei")
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 über die Flags -bom / -av / -tos ausgewählten Elemente als CSV-Datei(en)")
sp_csv.register("action", "store_after_check", ArgparseDirectoryCheck)
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_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())
if os.environ.get("DB_PATH") is not None:
@@ -37,6 +38,8 @@ def main():
csv_handler = CSVHandler()
sql_handler = SQLFileHandler()
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"
sql_source_filename = "sivas_replika.sql"
@@ -48,29 +51,59 @@ def main():
new_bom.create_tmp_table()
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
bom_processing.write_new_bom()
# Ausgabe in Konsole
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":
if args["verbose"]:
bom_data = new_bom.get_verbose_data()
else:
bom_data = new_bom.get_compact_data()
filedir = args["out_dir"]
filename = f"BOM_{args["parent_code"]}_final.csv"
filepath = os.path.join(filedir, filename)
csv_handler.write_from_dict(data=bom_data, filedir=filedir, filename=filename)
filenames = []
file_data = []
if args["open_csv"]:
subprocess.run(['cmd', '/c', 'start', '', filepath], shell=True)
# CSV-Ausgabe der aufbereiteten Stückliste
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:
NotImplementedError
@@ -828,5 +861,148 @@ class BOMProcessing:
self.insert()
self.update()
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__":
main()
Binary file not shown.
+308
View File
@@ -0,0 +1,308 @@
<?xml version="1.0" encoding="UTF-8"?><sqlb_project><db path="test.db" readonly="0" foreign_keys="1" case_sensitive_like="0" temp_store="0" wal_autocheckpoint="1000" synchronous="2"/><attached/><window><main_tabs open="structure browser pragmas query" current="3"/></window><tab_structure><column_width id="0" width="300"/><column_width id="1" width="0"/><column_width id="2" width="100"/><column_width id="3" width="3270"/><column_width id="4" width="0"/><expanded_item id="0" parent="1"/><expanded_item id="1" parent="1"/><expanded_item id="2" parent="1"/><expanded_item id="3" parent="1"/></tab_structure><tab_browse><table title="PARTS" custom_title="0" dock_id="1" table="4,5:mainPARTS"/><dock_state state="000000ff00000000fd00000001000000020000058b00000395fc0100000001fc000000000000058b0000012100fffffffa000000000100000002fb000000160064006f0063006b00420072006f00770073006500310100000000ffffffff0000012100fffffffb000000160064006f0063006b00420072006f00770073006500340000000000ffffffff00000000000000000000058b0000000000000004000000040000000800000008fc00000000"/><default_encoding codec=""/><browse_table_settings><table schema="main" name="COMP" show_row_id="0" encoding="" plot_x_axis="" unlock_view_pk="_rowid_" freeze_columns="0"><sort><column index="1" mode="0"/></sort><column_widths><column index="1" value="50"/><column index="2" value="79"/><column index="3" value="48"/><column index="4" value="90"/><column index="5" value="107"/><column index="6" value="48"/><column index="7" value="87"/><column index="8" value="52"/><column index="9" value="73"/><column index="10" value="76"/><column index="11" value="72"/><column index="12" value="63"/><column index="13" value="72"/></column_widths><filter_values/><conditional_formats/><row_id_formats/><display_formats/><hidden_columns/><plot_y_axes/><global_filter/></table><table schema="main" name="PARTS" show_row_id="0" encoding="" plot_x_axis="" unlock_view_pk="_rowid_" freeze_columns="0"><sort><column index="6" mode="1"/></sort><column_widths><column index="1" value="78"/><column index="2" value="300"/><column index="3" value="39"/><column index="4" value="53"/><column index="5" value="64"/><column index="6" value="108"/><column index="7" value="107"/><column index="8" value="41"/><column index="9" value="97"/><column index="10" value="126"/><column index="12" value="112"/><column index="13" value="135"/><column index="14" value="54"/><column index="15" value="51"/><column index="16" value="218"/><column index="17" value="195"/><column index="18" value="73"/><column index="19" value="65"/><column index="20" value="76"/><column index="21" value="113"/><column index="22" value="76"/><column index="23" value="70"/><column index="24" value="102"/><column index="25" value="52"/></column_widths><filter_values><column index="4" value="M"/><column index="0" value="822066089"/></filter_values><conditional_formats/><row_id_formats/><display_formats/><hidden_columns/><plot_y_axes/><global_filter/></table><table schema="main" name="RD_COMP" show_row_id="0" encoding="" plot_x_axis="" unlock_view_pk="_rowid_" freeze_columns="0"><sort><column index="1" mode="0"/></sort><column_widths><column index="1" value="35"/><column index="2" value="78"/><column index="3" value="105"/><column index="4" value="78"/><column index="5" value="45"/><column index="6" value="105"/><column index="7" value="122"/></column_widths><filter_values><column index="6" value="5"/></filter_values><conditional_formats/><row_id_formats/><display_formats/><hidden_columns/><plot_y_axes/><global_filter/></table><table schema="main" name="STKL_REGEL" show_row_id="0" encoding="" plot_x_axis="" unlock_view_pk="_rowid_" freeze_columns="0"><sort/><column_widths><column index="1" value="35"/><column index="2" value="82"/><column index="3" value="134"/><column index="4" value="44"/></column_widths><filter_values/><conditional_formats/><row_id_formats/><display_formats/><hidden_columns/><plot_y_axes/><global_filter/></table><table schema="main" name="VAR_TEIL_BEDINGUNG_2" show_row_id="0" encoding="" plot_x_axis="" unlock_view_pk="_rowid_" freeze_columns="0"><sort><column index="3" mode="0"/></sort><column_widths><column index="1" value="48"/><column index="2" value="140"/><column index="3" value="137"/><column index="4" value="102"/></column_widths><filter_values/><conditional_formats/><row_id_formats/><display_formats/><hidden_columns/><plot_y_axes/><global_filter/></table></browse_table_settings></tab_browse><tab_sql><sql name="1_create_tmp_not_identical">DROP TABLE IF EXISTS TMP_CODES_CASE_12_OR_13;
CREATE TABLE TMP_CODES_CASE_12_OR_13 (KOMPTEILENR TEXT NOT NULL, PRIMARY KEY (KOMPTEILENR));
WITH combined_bom AS (
SELECT C.KOMPTEILENR, COALESCE(C.LAENGE, 0) AS LAENGE
FROM COMP C
WHERE C.UEBTEILENR = '000000372'
UNION ALL
SELECT ChildCode, Uebergabelaenge
FROM RD_COMP
WHERE ParentCode = '000000372'
)
INSERT INTO TMP_CODES_CASE_12_OR_13
SELECT DISTINCT KOMPTEILENR
FROM (
SELECT KOMPTEILENR, LAENGE, COUNT(*) AS ANZAHL
FROM combined_bom
GROUP BY KOMPTEILENR, LAENGE
)
WHERE ANZAHL = 1;
SELECT * FROM TMP_CODES_CASE_12_OR_13</sql><sql name="2_create_tmp_not_same_pos">DROP TABLE IF EXISTS TMP_CODES_CASE_13;
CREATE TABLE TMP_CODES_CASE_13 (KOMPTEILENR TEXT NOT NULL, PRIMARY KEY(KOMPTEILENR));
WITH combined_bom AS (
SELECT KOMPTEILENR, POSNR
FROM COMP
WHERE UEBTEILENR = '000000372'
AND KOMPTEILENR IN (SELECT * FROM TMP_CODES_CASE_12_OR_13)
UNION ALL
SELECT ChildCode, Positionsnummer
FROM RD_COMP
WHERE ParentCode = '000000372'
AND ChildCode IN (SELECT * FROM TMP_CODES_CASE_12_OR_13)
)
INSERT INTO TMP_CODES_CASE_13 (KOMPTEILENR)
SELECT DISTINCT KOMPTEILENR
FROM (
SELECT KOMPTEILENR, COUNT(*) AS ANZAHL
FROM combined_bom
GROUP BY KOMPTEILENR, POSNR
)
WHERE ANZAHL = 1;
SELECT * FROM TMP_CODES_CASE_13</sql><sql name="3_get_case_11_pos">DROP TABLE IF EXISTS TMP_POSNRS_CASE_11;
CREATE TABLE TMP_POSNRS_CASE_11 (UEBTEILENR TEXT NOT NULL,
POS_ALT INTEGER NOT NULL,
POS_NEU INTEGER NOT NULL,
PRIMARY KEY(POS_NEU));
INSERT INTO TMP_POSNRS_CASE_11 (UEBTEILENR, POS_ALT, POS_NEU)
SELECT C.UEBTEILENR, C.POSNR AS POS_ALT, RD.Positionsnummer AS POS_NEU
FROM RD_COMP RD
LEFT JOIN TMP_CODES_CASE_12_OR_13 TMP
ON RD.ChildCode = TMP.KOMPTEILENR
LEFT JOIN COMP C
ON RD.ParentCode = C.UEBTEILENR
AND RD.ChildCode = C.KOMPTEILENR
AND RD.Uebergabelaenge = COALESCE(C.LAENGE, 0)
WHERE RD.ParentCode = '000000372'
AND TMP.KOMPTEILENR IS NULL;
SELECT * FROM TMP_POSNRS_CASE_11</sql><sql name="4_get_case_12_pos">DROP TABLE IF EXISTS TMP_POSNRS_CASE_12;
CREATE TABLE TMP_POSNRS_CASE_12 (UEBTEILENR TEXT NOT NULL,
POS_ALT INTEGER NOT NULL,
POS_NEU INTEGER NOT NULL,
PRIMARY KEY(POS_NEU));
INSERT INTO TMP_POSNRS_CASE_12 (UEBTEILENR, POS_ALT, POS_NEU)
SELECT C.UEBTEILENR, C.POSNR AS POS_ALT, RD.Positionsnummer AS POS_NEU
FROM RD_COMP RD
LEFT JOIN TMP_CODES_CASE_13 TMP
ON RD.ChildCode = TMP.KOMPTEILENR
LEFT JOIN COMP C
ON RD.ParentCode = C.UEBTEILENR
AND RD.ChildCode = C.KOMPTEILENR
AND RD.Positionsnummer = C.POSNR
WHERE RD.ParentCode = '000000372'
AND TMP.KOMPTEILENR IS NULL
AND RD.Positionsnummer NOT IN (SELECT POSNR FROM TMP_POSNRS_CASE_11);
SELECT * FROM TMP_POSNRS_CASE_12;</sql><sql name="5_get_case_131_pos">DROP TABLE IF EXISTS TMP_POSNRS_CASE_131;
CREATE TABLE TMP_POSNRS_CASE_131 (POSNR INTEGER NOT NULL, PRIMARY KEY(POSNR));
INSERT INTO TMP_POSNRS_CASE_131
SELECT RD.Positionsnummer AS POSNR
FROM RD_COMP RD
LEFT JOIN COMP C
ON RD.ParentCode = C.UEBTEILENR
AND RD.ChildCode = C.KOMPTEILENR
AND RD.Uebergabelaenge = COALESCE(C.LAENGE, 0)
WHERE RD.ParentCode = '000000372'
AND RD.ChildCode IN (SELECT * FROM TMP_CODES_CASE_13)
AND C.KOMPTEILENR IS NULL;
SELECT * FROM TMP_POSNRS_CASE_131;</sql><sql name="6_get_case_132_pos">DROP TABLE IF EXISTS TMP_POSNRS_CASE_132;
CREATE TABLE TMP_POSNRS_CASE_132 (UEBTEILENR TEXT NOT NULL,
POS_ALT INTEGER NOT NULL,
POS_NEU INTEGER NOT NULL,
PRIMARY KEY(POS_NEU));
INSERT INTO TMP_POSNRS_CASE_132 (UEBTEILENR, POS_ALT, POS_NEU)
SELECT C.UEBTEILENR, C.POSNR AS POS_ALT, RD.Positionsnummer AS POS_NEU
FROM RD_COMP RD
INNER JOIN COMP C
ON RD.ParentCode = C.UEBTEILENR
AND RD.ChildCode = C.KOMPTEILENR
AND RD.Uebergabelaenge = COALESCE(C.LAENGE, 0)
WHERE RD.ParentCode = '000000372'
AND RD.ChildCode IN (SELECT * FROM TMP_CODES_CASE_13);
SELECT * FROM TMP_POSNRS_CASE_132;</sql><sql name="7_get_ids_to_delete">WITH COMBINED_UPDATE_DATA AS (
SELECT * FROM TMP_POSNRS_CASE_11
UNION
SELECT * FROM TMP_POSNRS_CASE_12
UNION
SELECT * FROM TMP_POSNRS_CASE_132
)
--INSERT INTO TMP_IDS_TO_DELETE
SELECT C.ROWID AS COMP_ROWID, B.ROWID AS BED_ROWID, R.ROWID AS REG_ROWID
FROM COMP C
LEFT JOIN COMBINED_UPDATE_DATA CUD
ON C.UEBTEILENR = CUD.UEBTEILENR
AND C.POSNR = CUD.POS_ALT
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 = '000000372'
AND CUD.UEBTEILENR IS NULL</sql><sql name="get_update_data">DROP TABLE IF EXISTS TMP_UPDATE_DATA;
CREATE TABLE TMP_UPDATE_DATA (ROWID INTEGER NOT NULL,
POS_ALT INTEGER NOT NULL,
POS_NEU INTEGER NOT NULL,
ABW_ANZAHL INTEGER,
MENGE REAL,
LAENGE REAL,
ZUSCHNITT REAL,
DISPO_AKTIV_JN TEXT,
RUESTCODE TEXT,
BED_ROWID INTEGER,
REG_ROWID INTEGER,
UEB_LEISTEN_NR INTEGER,
LFD_NR INTEGER);
WITH ALL_POSNRS_TO_UPDATE AS (
SELECT * FROM TMP_POSNRS_CASE_11
UNION
SELECT * FROM TMP_POSNRS_CASE_12
UNION
SELECT * FROM TMP_POSNRS_CASE_132
)
INSERT INTO TMP_UPDATE_DATA (ROWID, POS_ALT, POS_NEU, ABW_ANZAHL, MENGE, LAENGE, ZUSCHNITT, DISPO_AKTIV_JN, RUESTCODE, BED_ROWID, REG_ROWID, UEB_LEISTEN_NR, LFD_NR)
SELECT C.ROWID,
P.POS_ALT,
RD.Positionsnummer AS POS_NEU,
-- Bestimmt Wert für Spalte 'ABW_ANZAHL': NULL, wenn Pos. nicht längenabhängig, sonst Wert 'Menge' aus CSV
CASE
WHEN RD.Uebergabelaenge = 0 THEN NULL
ELSE RD.Menge
END AS ABW_ANZAHL,
-- Bestimmt Wert für Spalte 'MENGE': Berechnung Dezimalwert, wenn Pos. längenabhängig, sonst Wert 'Menge' aus CSV
CASE
WHEN RD.Uebergabelaenge = 0 THEN RD.Menge
ELSE RD.Menge * (RD.Uebergabelaenge + COALESCE(C.ZUSCHNITT, 0)) / 1000
END AS MENGE,
-- Bestimmt Wert für Spalte 'LAENGE': NULL, wenn Pos. nicht längenabhängig, sonst Wert 'Uebergabelaenge' aus CSV
CASE
WHEN RD.Uebergabelaenge = 0 THEN NULL
ELSE RD.Uebergabelaenge
END AS LAENGE,
C.ZUSCHNITT,
C.DISPO_AKTIV_JN,
C.RUESTCODE,
B.ROWID,
R.ROWID,
B.UEB_LEISTEN_NR,
R.LFD_NR
FROM ALL_POSNRS_TO_UPDATE P
INNER JOIN COMP C
ON P.UEBTEILENR = C.UEBTEILENR
AND P.POS_ALT = C.POSNR
INNER JOIN RD_COMP RD
ON P.UEBTEILENR = RD.ParentCode
AND P.POS_NEU = RD.Positionsnummer
LEFT JOIN VAR_TEIL_BEDINGUNG_2 B
ON P.UEBTEILENR = B.UEBTEILENR
AND P.POS_ALT = B.POSNR
LEFT JOIN STKL_REGEL R
ON P.UEBTEILENR = R.UEBTEILENR
AND P.POS_ALT = R.POSNR;
SELECT * FROM TMP_UPDATE_DATA</sql><sql name="TOS-Workflowmeldung">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 = '000000382'
AND (
B.UEB_LEISTEN_NR IS NOT NULL
OR R.LFD_NR IS NOT NULL
)
ORDER BY C.POSNR</sql><sql name="AV-Workflowmeldungen*">--längenabhängige Teilenummern herausfinden, die in beiden Stücklisten vorliegen
WITH laengenabh_codes_in_both_boms AS (
SELECT DISTINCT ChildCode
FROM RD_COMP
WHERE ParentCode = '000000382'
AND ChildCode in (
SELECT DISTINCT KOMPTEILENR
FROM COMP
WHERE UEBTEILENR = '000000382'
AND COALESCE(LAENGE, 0) != 0
)
)
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