diff --git a/oracle/init-scripts/01_init.sql b/oracle/init-scripts/01_init.sql index 97739b9..cfd421f 100644 --- a/oracle/init-scripts/01_init.sql +++ b/oracle/init-scripts/01_init.sql @@ -18,6 +18,7 @@ CREATE TABLE WATTANA.KPI_KONFEKTIONAERE ( ID NUMBER PRIMARY KEY, AKTUALISIERT_AM TIMESTAMP, KONFEKTIONAER VARCHAR2(200), + KONFEKTIONAER_ID NUMBER, QUOTE_ERSTBESTAETIGUNG NUMBER(7,4), PROZENT_LIEFERTREUE NUMBER(7,4), ANTEIL_PROZENT_LIEFERTERMINUNTERSCHREITUNG NUMBER(7,4), @@ -30,3 +31,45 @@ CREATE TABLE WATTANA.KPI_KONFEKTIONAERE ( MITTLERE_DURCHLAUFZEIT_ANZAHL_TAGE NUMBER(10), MITTLERER_QUALITAETSSCORE_PSM NUMBER(5,4) ); + +CREATE TABLE WATTANA.EXTERN_MIS ( + "ID" NUMBER PRIMARY KEY, + "PA" NUMBER, + "PA Pos" NUMBER, + "VK Auftrag" NUMBER, + "Konfektionär" VARCHAR2(1000), + "Lieferantnr." NUMBER +); + +CREATE TABLE WATTANA.EXTERN_PSM ( + "ID" NUMBER PRIMARY KEY, + "VK Auftrag" NUMBER, + "Artikelbez." VARCHAR2(1000), + "Auftragsmenge" NUMBER, + "Kunde" VARCHAR2(1000), + "PA" NUMBER, + "PA Pos" NUMBER, + "PSM gemeldet am" TIMESTAMP, + "Konfektionär" VARCHAR2(1000), + "Lieferantnr." NUMBER, + "Artikelnr." VARCHAR2(300), + "LT Kunde bestätigt" DATE, + "Export Ist" DATE, + "1.bestät. Import Konfektionär" DATE, + "Import Ist" DATE, + "Ablief.(Import Ist+Transport)" DATE, + "Wareneingang am" DATE, + "Wareneingang geprüft" VARCHAR2(10), + "Täglicher Ausstoss" NUMBER, + "Zuschnitt am" DATE, + "Teile in Zuschnitt" NUMBER, + "Teile im Nähband" NUMBER, + "Fertigware aus Nähband" NUMBER, + "Teile kontrolliert" NUMBER, + "Teile verpackt in Karton" NUMBER, + "Anzahl Bänder" NUMBER, + "Anzahl Näher" NUMBER, + "Arbeitsstunden pro Näher" NUMBER, + "Anzahl Arbeitstage pro Woche" NUMBER, + "Blockauftrag" VARCHAR2(10) +); \ No newline at end of file diff --git a/prototypes/01_first-look_20260603.py b/prototypes/01-1_first-look_20260603.py similarity index 98% rename from prototypes/01_first-look_20260603.py rename to prototypes/01-1_first-look_20260603.py index afa61a5..43c2c71 100644 --- a/prototypes/01_first-look_20260603.py +++ b/prototypes/01-1_first-look_20260603.py @@ -25,9 +25,16 @@ data_t1_jobs = data_t1 / "MIS-Auträge_22.csv" assert data_t1_jobs.exists() data_t1_PSM = data_t1 / "Produktionsstandsmeldungen.csv" assert data_t1_PSM.exists() + # %% # // MIS-Aufträge -# pl.read_csv(data_t1_jobs, encoding="windows-1252", separator=";") +# schema_override = { +# "Fertigungsminuten pro Artikel": pl.String, +# } +schema_override = None +pl.read_csv( + data_t1_jobs, encoding="windows-1252", separator=";", schema_overrides=schema_override +) # %% diff --git a/prototypes/01-2_cleanup_MIS-file.py b/prototypes/01-2_cleanup_MIS-file.py new file mode 100644 index 0000000..b4d50fc --- /dev/null +++ b/prototypes/01-2_cleanup_MIS-file.py @@ -0,0 +1,408 @@ +# %% +import datetime +import enum +import importlib +import json +from pathlib import Path +from pprint import pprint +from typing import Any + +import polars as pl +import sqlalchemy as sql + +from wattanalyse import db + +importlib.reload(db) + +# %% +PROJECT_BASE = Path(__file__).parents[1] +DATA_PTH = PROJECT_BASE / "data" +assert DATA_PTH.exists() +# %% +data_t1 = DATA_PTH / "PSM/20260507" +assert data_t1.exists() +# %% +# data_t1_jobs = data_t1 / "MIS-Auträge_22.csv" +data_t1_jobs = data_t1 / "MIS Auträge ab 22.csv" +assert data_t1_jobs.exists() +data_t1_PSM = data_t1 / "Produktionsstandsmeldungen.csv" +assert data_t1_PSM.exists() +# %% +# // MIS-Aufträge +schema_override = { + "Fertigungsminuten pro Artikel": pl.String, + "Fertigungsminuten pro PA": pl.String, + "Auftragsmenge offen": pl.String, + "Gutschrift Menge": pl.String, + "PA Menge offen": pl.String, +} +# schema_override = None +data = pl.read_csv( + data_t1_jobs, encoding="windows-1252", separator=";", schema_overrides=schema_override +).head(-1) +# %% +faulty_cols = [ + "Fertigungsminuten pro Artikel", + "Fertigungsminuten pro PA", + "Auftragsmenge offen", + "Gutschrift Menge", + "PA Menge offen", +] +data = data.with_columns( + pl.col(faulty_cols) + .str.replace(r"\.(\d)$", r".${1}00") + .str.replace(r"\.(\d\d)$", r".${1}0") + .str.replace_all(r"\.", "") + .cast(pl.Int64) + .name.keep() +) +# %% +# cols = data.columns +# data = data.with_row_index("idx", offset=2) +# data = data.select(["idx"] + cols) +# data.head() + +# %% +data = data.select(["PA", "PA Pos", "VK Auftrag", "Konfektionär"]) +# // save data as raw +target = DATA_PTH / "MIS_20260507.arrow" +data.write_ipc(target) + +# %% +# !! schema not working because of faulty base data +# keep this schema for later, maybe helpful at later stages +# for prototyping just use a subset with the relevant features, especially "PA" + "PA Pos" +schema_MIS = { + "Muster neu / vor Ort": pl.String, + "PA Pos": pl.UInt32, + "Agentur": pl.String, + "Konfektionär bestätigt": pl.Int8, + "Auftragsart": pl.String, + "Geplante Fertigungsdauer (Tage)": pl.UInt64, + "Geplanter Ausstoß pro Tag": pl.UInt64, + "PSM Import Ist": pl.Date, + "Export Ist": pl.Date, + "Kundenliefertermin bestätigt": pl.Date, + "Kundenliefertermin Soll": pl.Date, + "Kundenliefertermin bestätigt (erster)": pl.Date, + "PSM Gemeldet am": pl.Date, + "Kunde Kurzbezeichnung": pl.String, + "Artikelbezeichnung": pl.String, + "Artikelnummer": pl.String, + "PA Menge Soll": pl.UInt32, + "PA": pl.UInt64, + "VK Auftrag": pl.UInt64, + "PSM Bereits in Produktion": pl.UInt32, + "Konfektionär": pl.String, + "Auftragseingang": pl.Date, + "Export geplant": pl.Date, + "VK Auftrag Pos": pl.UInt32, + "Import Ist": pl.Date, + "Importtermin bestätigt": pl.Int8, + "Kundenliefertermin geplant (Import + Transport) autom. berechnet": pl.Date, + "1. bestätigter Import Konfektionär": pl.Date, + "PSM Grund Lieferverschiebung": pl.String, + "Saison": pl.Int64, + "Auftragsstatus": pl.String, + "Kd. Auftrag": pl.String, + "Schweißartikel": pl.String, + "Konfektionsland": pl.String, + "Artikelfarbe": pl.String, + "Materialbedarf Kosten Soll gesamt": pl.Decimal(scale=2), + "ASD Nr.": pl.String, + "Kunde": pl.String, + "Konzern": pl.String, + "Lieferort": pl.String, + "Kommentar Lieferant KW X": pl.String, + "Kommentar BWBM KW X": pl.String, + "Auftragsmenge": pl.UInt32, + "Auftragsmenge geliefert": pl.UInt32, + "Auftragsmenge offen": pl.UInt32, + "Angebotspreis kalk pro Artikel aus KalkSchema": pl.Decimal(scale=2), + "VK Preis": pl.Decimal(scale=2), + "VK Rechnungen bezahlt am": pl.String, + "VK Rechnungen netto bezahlt": pl.Decimal(scale=2), + "VK Gutschriften Info": pl.String, + "RV Vertragslaufzeit Beginn": pl.Date, + "RV Vertragslaufzeit Ende": pl.Date, + "Auftrag angelegt am": pl.Date, + "Kundenliefertermin Ist (Letzte Lieferung)": pl.Date, + "Exportabschluss vollständig am": pl.Date, + "LP kalk pro Artikel aus Auftragspos.": pl.Decimal(scale=2), + "PA aktiv (PL auf PA umstellen)": pl.Int8, + "Vorfertigungsstufen in PA": pl.String, + "PA Status": pl.String, + "PA Art": pl.String, + "PA Typ": pl.String, + "Dach-PA": pl.String, + "MEL": pl.String, + "Nachlieferungen": pl.String, + "Ersatzlieferungen": pl.String, + "Konfektionär aus Kalkulation": pl.String, + "Konfektionsland aus Kalkulation": pl.String, + "LP kalk gesamt aus Auftragspos.": pl.Decimal(scale=2), + "LP Ist pro Artikel aus PA-Stufe Fertigung": pl.Decimal(scale=2), + "LP bestätigt": pl.Int8, + "LP Ist gesamt aus PA-Stufe Fertigung": pl.Decimal(scale=2), + "Info PPS (aus PA)": pl.String, + "PA Menge offen": pl.UInt32, + "PSM Teile in Zuschnitt": pl.UInt32, + "PSM Teile in Nähband": pl.UInt32, + "Info PPS (allgemein)": pl.String, + "MwVZ kalk pro Artikel aus Auftragpos.": pl.Decimal(scale=2), + "MwVZ kalk gesamt aus Auftragpos.": pl.Decimal(scale=2), + "MwVZ berechnet pro Artikel (Basis PA Stüli)": pl.Decimal(scale=2), + "MwVZ berechnet gesamt (Basis PA Stüli)": pl.Decimal(scale=2), + "MwVZ berechnet Bemerkung (Basis PA Stüli)": pl.String, + "MwVZ Ist pro Artikel": pl.Decimal(scale=2), + "MwVZ Ist gesamt": pl.Decimal(scale=2), + "Kalk/Ist-Preise aus ELO": pl.String, + "Materialkosten kalk gesamt aus KalkSchema": pl.Decimal(scale=2), + "Herstellkosten kalk pro Artikel aus KalkSchema": pl.Decimal(scale=2), + "Herstellkosten kalk gesamt aus KalkSchema": pl.Decimal(scale=2), + "Materialbedarf Kosten Soll pro Artikel": pl.Decimal(scale=2), + "Materialkosten Überlieferung pro Artikel": pl.Decimal(scale=2), + "Materialkosten Überlieferung gesamt": pl.Decimal(scale=2), + "Materialkosten Komplettlieferung pro Artikel": pl.Decimal(scale=2), + "Materialkosten Komplettlieferung gesamt": pl.Decimal(scale=2), + "Material Bestellwert pro Artikel": pl.Decimal(scale=2), + "Material Bestellwert gesamt": pl.Decimal(scale=2), + "Material bereits bezahlt": pl.Decimal(scale=2), + "Material noch nicht bezahlt - ELO Rechnung vorhanden": pl.Decimal(scale=2), + "Transportkosten Import kalk pro Artikel aus KalkSchema oder Auftragspos.": pl.Decimal( + scale=2 + ), + "Transportkosten Import kalk gesamt aus KalkSchema oder Auftragspos.": pl.Decimal( + scale=2 + ), + "Transportkosten Import Ist gesamt": pl.Decimal(scale=2), + "Transportkosten Import Ist pro Artikel": pl.Decimal(scale=2), + "Transportkosten Export kalk pro Artikel aus KalkSchema oder Auftragspos. ": pl.Decimal( + scale=2 + ), + "Transportkosten Export kalk gesamt aus KalkSchema oder Auftragspos.": pl.Decimal( + scale=2 + ), + "Umsatz Auftragsmenge gesamt": pl.Decimal(scale=2), + "Transportkosten Export Ist gesamt": pl.Decimal(scale=2), + "Transportkosten Export Ist pro Artikel": pl.Decimal(scale=2), + "Zuschlag (Stickerei/Zutaten)": pl.Decimal(scale=2), + "LP + MwVz kalk gesamt": pl.Decimal(scale=2), + "LP + MwVz Ist gesamt": pl.Decimal(scale=2), + "Stückliste Freigabe am": pl.Date, + "Kundenmuster Freigabe am": pl.Date, + "Lieferanten ABs komplett am": pl.Date, + "Technische Unterlagen/Muster erstellt am": pl.Date, + "Etikettlayout erstellt/Freigabe Kunde am": pl.Date, + "Schnibi": pl.Date, + "VK Rechnung Kz.": pl.String, + "Kapazität pro Tag pro Näher (min)": pl.UInt16, + "Gesamtkapazität pro Tag (min)": pl.UInt16, + "Fertigungsminuten pro Artikel": pl.UInt32, + "Fertigungsminuten pro PA": pl.UInt32, + "APP Nr.": pl.String, + "VK Auftrag Los": pl.Int64, + "Umsatz Auftragsmenge offen": pl.Decimal(scale=2), + "Umsatz fakturiert": pl.Decimal(scale=2), + "Kundenliefertermin bestätigt (Monat/Jahr)": pl.Date, + "Materialkosten zu Kalk Preis aus Kalk.-Stüli": pl.Decimal(scale=2), + "Materialkosten zu EK Preis aus Kalk.-Stüli": pl.Decimal(scale=2), + "Materialkosten zu EKD Preis aus Kalk.-Stüli": pl.Decimal(scale=2), + "Materialkosten zu Staffel Preis aus Kalk.-Stüli": pl.Decimal(scale=2), + "Materialkosten zu EK Preis aus Soll-Prod.Stüli": pl.Decimal(scale=2), + "Materialkosten zu EKD Preis aus Soll-Prod.Stüli": pl.Decimal(scale=2), + "Materialkosten zu Staffel Preis aus Soll-Prod.Stüli": pl.Decimal(scale=2), + "VK Rechnung erstellt am": pl.Date, + "Nationalisierungsabgabe kalk aus KalkSchema": pl.Decimal(scale=2), + "Materialkosten kalk pro Artikel aus KalkSchema": pl.Decimal(scale=2), + "Materialkosten Artikelstamm": pl.Decimal(scale=2), + "PA Menge Ist": pl.UInt32, + "Kundenliefertermin Ist (Letzte Lieferung) (Monat/Jahr)": pl.Date, + "Import Ist (Monat/Jahr)": pl.Date, + "Kalkulationen (alle) zum Artikel": pl.String, + "Kalkulation zu Auftrag": pl.String, + "Material Oberstoff Überlieferung in %": pl.Float64, + "Material Zutaten Überlieferung in %": pl.Float64, + "Lohnkonfektionsbestellnr": pl.String, + "VK Auftrag Pos Text": pl.String, + "PA Vorfertigung Menge": pl.UInt32, + "Preisanpassungen zu Artikel": pl.String, + "MwVZ kalk pro Artikel aus KalkSchema": pl.Decimal(scale=2), + "PA Vorfertigung Menge offen": pl.UInt32, + "PA Vorfertigung Menge Ist": pl.UInt32, + "RV Nr.": pl.String, + "VK Rechnung erstellt am Jahr": pl.UInt16, + "VK Kalk. Angebotspreise (Staffelpreise)": pl.String, + "Gutschrift Menge": pl.UInt32, + "Ausschreibung abgegeben am": pl.Date, + "VK Blockauftrag": pl.String, + "Lieferung im Jahr": pl.UInt16, + "LP kalk pro Artikel aus KalkSchema": pl.Decimal(scale=2), + "LP kalk gesamt aus KalkSchema": pl.Decimal(scale=2), + "Artikel Produktbereich": pl.String, + "VK Blockauftrag Pos": pl.Int32, + "Preisanpassung beantragt": pl.String, + "Preisanpassung erhalten": pl.String, + "VK Preis vor Preisanpassung": pl.Decimal(scale=2), + "VK Preis nach Preisanpassung": pl.Decimal(scale=2), + "Tagesplannr": pl.Int64, + "Abweichung Gesamtkosten pro Artikel Kalk zu Ist": pl.Decimal(scale=2), + "Abweichung Materialkosten pro Artikel Kalk zu Ist": pl.Decimal(scale=2), + "Abweichung Materialkosten pro Artikel Kalk zu Ist %": pl.Float64, + "Abweichung Lohnpreis pro Artikel Kalk zu Ist": pl.Decimal(scale=2), + "Abweichung Lohnpreis pro Artikel Kalk zu Ist %": pl.Float64, + "Abweichung MwVZ pro Artikel Kalk zu Ist": pl.Decimal(scale=2), + "Abweichung MwVZ pro Artikel Kalk zu Ist %": pl.Float64, + "Abweichung Transportkosten Export pro Artikel Kalk zu Ist": pl.Decimal(scale=2), + "Abweichung Transportkosten Export pro Artikel Kalk zu Ist %": pl.Float64, + "BANFen erstellt am (Prod.Planung)": pl.Date, + "Bestellfreigabe am": pl.Date, + "Abweichung Transportkosten Import pro Artikel Kalk zu Ist": pl.Decimal(scale=2), + "Abweichung Transportkosten Import pro Artikel Kalk zu Ist %": pl.Float64, + "Artikelgruppierung PPS": pl.String, + "Info QS": pl.String, + "Artikelgruppierung VK": pl.String, + "Mengenart": pl.String, + "Info Z/L": pl.String, + "EK Erste Bestellung erstellt am": pl.Date, + "Info VK": pl.String, + "Info PM": pl.String, + "EK Letzte Bestellung erstellt am": pl.Date, + "EK Letzte AB Oberstoff": pl.Date, + "EK Letzte AB Zutaten": pl.Date, + "Info EK": pl.String, + "Info BuHa": pl.String, + "Info Musternäherei": pl.String, + "VK Ansprechpartner": pl.String, + "Artikel Matchcode": pl.String, + "Artikel Produktgruppe": pl.String, + "Artikel Thema": pl.String, + "PSM Wareneingang geprüft": pl.Int8, + "LV gesendet": pl.Date, + "LV bestätigt": pl.Date, + "VK Suchmerkmal": pl.String, + "PSM Wareneingang am": pl.Date, + "VK Rechnung Nr.": pl.String, + "Lieferschein Nr.": pl.String, + "QS Prüfung vor Ort erforderlich": pl.Int8, + "RV Nr. mit Artikel": pl.String, + "PSM täglicher Ausstoß": pl.UInt32, + "QS Lieferung Qualität aus ELO": pl.String, + "PSM Anzahl Bänder": pl.UInt32, + "PSM Anzahl Näher": pl.UInt32, + "PSM Arbeitsstunden pro Tag pro Näher": pl.UInt8, + "PSM Arbeitstage pro Woche": pl.UInt8, + "PSM Zuschnitt am": pl.Date, + "PSM Fertigware aus Nähband": pl.UInt32, + "PSM Teile kontrolliert": pl.UInt32, + "PSM Teile verpackt": pl.UInt32, + "PSM Hängeware": pl.Int8, + "Kundenliefertermin Verschiebungen": pl.UInt32, + "PSM Anzahl Paletten": pl.UInt32, + "PSM Anzahl Kartons": pl.UInt32, + "PSM Teile in Färberei": pl.UInt32, + "PSM Teile in Stickerei": pl.UInt32, + "Güteprüfung beantragt": pl.Int8, + "Güteprüfung erforderlich": pl.Int8, + "Güteprüfung Termin": pl.Date, + "Güteprüfung Ort": pl.String, + "Materialdatei erforderlich": pl.Int8, + "Materialdatei beantragt am": pl.Date, + "Materialdatei Freigabe am": pl.Date, + "Export bestätigt": pl.Int8, + "MEL gesendet": pl.Int8, + "Lieferart": pl.String, + "Schnittfreigabe": pl.Date, + "Schnibi gesendet an": pl.String, + "Etiketten Druckfreigabe": pl.Date, + "Sonderkommissionierung": pl.Int8, + "Sonderkommissionierung Kosten": pl.Decimal(scale=2), + "Artikel Gewicht in g": pl.UInt64, + "Nach-/Ersatzlieferung Transportkosten": pl.Decimal(scale=2), + "HPZ (Herstellerprüfzertifikat) eingereicht": pl.Int8, + "Stückliste Freigabe Bemerkung": pl.String, + "Schnittfreigabe Bemerkung": pl.String, + "RV Vertragsmenge gesamt (BA)": pl.UInt32, + "RV Vertragsmenge abgerufen gesamt (BA)": pl.UInt32, + "RV Vertragsmenge offen gesamt (BA)": pl.UInt32, + "RV Auftragsmenge (DA)": pl.UInt32, + "RV Auftragsmenge geliefert (DA)": pl.UInt32, + "Vertragsstrafe Belegnr. intern/extern mit Belegdatum aus ELO": pl.String, + "RV Auftragsmenge offen (DA)": pl.UInt32, + "RV Forecastmenge": pl.UInt32, + "QS Auftrag aus VK gedruckt": pl.Int8, + "TU gespeichert in Auftrag": pl.Int8, + "Mail Muster für Proforma": pl.Int8, + "Musterliste": pl.Int8, + "Vertragsstrafe Info aus ELO": pl.String, + "EP (Endprüfprotokoll)": pl.Int8, + "ZP (Zwischenprüfprotokoll)": pl.Int8, + "Lagen Laminat": pl.String, + "Workflowart": pl.String, + "Vertragsstrafe Grund aus ELO": pl.String, + "RV Sortierung": pl.String, + "EK Lieferzeit (längste) Oberstoff in Wochen aus Kalk.Stüli": pl.String, + "EK Lieferzeit (längste) Zutaten in Wochen aus Kalk.Stüli": pl.String, + "Vertragsstrafe Verzugstage aus ELO": pl.String, + "Vertragsstrafe Betrag aus ELO": pl.String, + "RV Mindestmenge (BA)": pl.String, + "QS Ansprechpartner für Konfektionär": pl.String, + "Vertragsstrafe weiterbelastet an (Weiterbelastung-Nr.) aus ELO": pl.String, + "Vertragsstrafe Weiterbelastung Betrag aus ELO": pl.Decimal(scale=2), + "Vertragsstrafe Gutschrift Nr. aus ELO": pl.String, + "Vertragsstrafe Gutschrift Betrag aus ELO": pl.Decimal(scale=2), + "Vertragsstrafe fiktiv Betrag LT Soll zu LT bestätigt (letzter)": pl.Decimal(scale=2), + "Vertragsstrafe fiktiv Betrag LT Soll zu LT Ist": pl.Decimal(scale=2), + "Ausschreibung Lieferzeit in Tagen (Mo-Fr)": pl.UInt64, + "Konfektionär Gesamtanzahl Näher": pl.UInt64, + "QS VP Muster erforderlich": pl.Int8, + "Abweichung LT Soll zu LT bestätigt (letzter) in Tagen (Mo-Fr)": pl.UInt64, + "Abweichung LT Soll zu LT Ist in Tagen (Mo-Fr)": pl.UInt64, + "RV Mindestmenge geliefert (BA)": pl.UInt32, + "RV Mindestmenge offen (BA)": pl.UInt32, + "RV unverbindliche Menge (BA)": pl.UInt32, + "RV unverbindliche Menge geliefert (BA)": pl.UInt32, + "RV unverbindliche Menge offen (BA)": pl.UInt32, + "RV unverbindliche Restmenge zur Maximalmenge (BA)": pl.UInt32, + "RV unverbindliche Restmenge zur Maximalmenge geliefert (BA)": pl.UInt32, + "RV unverbindliche Restmenge zur Maximalmenge offen (BA)": pl.UInt32, + "QS Lieferung Qualität Bemerkung aus ELO": pl.String, + "Abweichung 'Export Ist' zu 'Zuschnitt am' (Mo-Fr)": pl.UInt64, + "Lieferschein erstellt am": pl.Date, + "Materialdatei EK abgeschlossen": pl.String, + "Lademeter Export": pl.String, + "Palettenanzahl Import": pl.UInt64, + "Transportzeit Konfektionär zu Kunde": pl.UInt32, + "Abweichung LT bestätigt zu LT geplant": pl.UInt64, + "Lieferadresse": pl.String, +} +# %% +data.filter(pl.col("LP kalk gesamt aus KalkSchema").str.contains("6.072")).select( + "LP kalk gesamt aus KalkSchema" +) +# %% +data = data.cast(schema_MIS) +# %% +df = pl.DataFrame( + { + "auftrag_id": [1, 2, 3, 4, 5], + "defekte_zahlen": ["3.11", "1.2", "1.250.000", "500", "1.0"], + } +) + +# 2. Bereinigung durchführen +df_bereinigt = df.with_columns( + pl.col("defekte_zahlen") + # Schritt A: Wenn nur 1 Ziffer nach dem Punkt steht (z.B. .2), zwei Nullen anhängen + .str.replace(r"\.(\d)$", r".${1}00") + # Schritt B: Wenn 2 Ziffern nach dem Punkt stehen (z.B. .11), eine Null anhängen + .str.replace(r"\.(\d\d)$", r".${1}0") + # Schritt C: Alle Punkte entfernen (da es reine Tausendertrennzeichen sind) + .str.replace_all(r"\.", "") + # Schritt D: In eine Ganzzahl (Integer) umwandeln + .cast(pl.Int64) + .alias("saubere_zahlen") +) +# %% +df_bereinigt +# %% diff --git a/prototypes/03-2_fill_oracle-db.py b/prototypes/03-2_fill_oracle-db.py new file mode 100644 index 0000000..04a3460 --- /dev/null +++ b/prototypes/03-2_fill_oracle-db.py @@ -0,0 +1,111 @@ +# %% +import importlib +from pathlib import Path +from pprint import pprint + +import external_code +import oracledb +import polars as pl + +import wattanalyse +from wattanalyse import constants, db + +importlib.reload(wattanalyse) +importlib.reload(constants) +importlib.reload(external_code) +importlib.reload(db) +# %% +PROJECT_BASE = Path(__file__).parents[1] +DATA_PTH = PROJECT_BASE / "data" +assert DATA_PTH.exists() +# %% + +mis_data = DATA_PTH / "MIS_20260507.arrow" +psm_data = DATA_PTH / "PSM_20260507.arrow" + +assert mis_data.exists() +assert psm_data.exists() +# %% +# // prepare +data_mis = pl.read_ipc(mis_data) +select_cols = data_mis.columns +data_mis = data_mis.with_row_index("ID", offset=1) +data_mis = data_mis.select(["ID"] + select_cols) +data_mis.head() + +# %% +data_mis = ( + data_mis.with_columns( + pl.col("Konfektionär").str.replace(r" - [^-]+$", "").alias("Konfektionär_"), + pl.col("Konfektionär") + .str.extract(r" - ([^-]+)$", 1) + .cast(pl.UInt64) + .alias("Lieferantnr."), + ) + .drop("Konfektionär") + .rename({"Konfektionär_": "Konfektionär"}) + .with_columns( + pl.col("Konfektionär").str.strip_chars(" "), + ) +) +# %% +new_mis_data = DATA_PTH / "MIS_prep_20260507.arrow" +data_mis.write_ipc(new_mis_data) +#################################### +# %% +konf_ids = data_mis.select(["Konfektionär", "Lieferantnr."]).unique( + subset=["Konfektionär"], keep="first" +) +# %% +data_psm = pl.read_ipc(psm_data) +select_cols = data_psm.columns +data_psm = data_psm.with_row_index("ID", offset=1).with_columns( + pl.col("Konfektionär").str.strip_chars(" ") +) +data_psm.head() +# %% +select_cols = data_psm.columns +konf_idx = select_cols.index("Konfektionär") +select_cols.insert(konf_idx + 1, "Lieferantnr.") +data_psm = data_psm.join(konf_ids, on="Konfektionär", how="left").select(select_cols) +data_psm.head() +# %% +new_psm_data = DATA_PTH / "PSM_prep_20260507.arrow" +data_psm.write_ipc(new_psm_data) +# %% +# // save to database +new_mis_data = DATA_PTH / "MIS_prep_20260507.arrow" +data_mis = pl.read_ipc(new_mis_data) +new_psm_data = DATA_PTH / "PSM_prep_20260507.arrow" +data_psm = pl.read_ipc(new_psm_data) +data_psm.head() +# %% +conn = oracledb.connect( + user=constants.USER_CFG.Datenbank.NUTZER, + password=constants.USER_CFG.Datenbank.PASSWORT, + host=constants.USER_CFG.Datenbank.HOST, + port=constants.USER_CFG.Datenbank.PORT, + service_name=constants.USER_CFG.Datenbank.SERVICE_NAME, +) + +# %% +stmts = external_code.oracle_generate_sql_insert("EXTERN_MIS", data_mis.columns) +external_code.oracle_save_polars(conn, stmts, data_mis) +# %% +stmts = external_code.oracle_generate_sql_insert("EXTERN_PSM", data_psm.columns) +external_code.oracle_save_polars(conn, stmts, data_psm) +# %% +schema = db.extern_MIS_t_schema +df = external_code.oracle_load_table_as_polars(conn, "EXTERN_MIS", schema=schema).collect() +df +# %% +schema = db.extern_prod_order_t_schema +df = external_code.oracle_load_table_as_polars(conn, "EXTERN_PSM", schema=schema).collect() +df +# %% +# // alter table for aggregates of supplier +stmt = 'ALTER TABLE "KPI_KONFEKTIONAERE" ADD ("KONFEKTIONAER_ID" NUMBER);' +with conn.cursor() as cursor: + cursor.execute(stmt) + conn.commit() +# %% diff --git a/src/wattanalyse/db.py b/src/wattanalyse/db.py index 727265f..9b6da40 100644 --- a/src/wattanalyse/db.py +++ b/src/wattanalyse/db.py @@ -84,7 +84,7 @@ MD_INTERNAL.create_all(ENGINE_INTERNAL) # ** read extern_prod_order_t_schema: dict[str, type[pl.DataType]] = { - "VK Auftrag": pl.UInt32, + "VK Auftrag": pl.UInt64, "Artikelbez.": pl.String, "Auftragsmenge": pl.UInt32, "Kunde": pl.String, @@ -92,6 +92,7 @@ extern_prod_order_t_schema: dict[str, type[pl.DataType]] = { "PA Pos": pl.UInt32, "PSM gemeldet am": pl.Datetime, "Konfektionär": pl.String, + "Lieferantnr.": pl.UInt64, "Artikelnr.": pl.String, "LT Kunde bestätigt": pl.Date, "Export Ist": pl.Date, @@ -107,13 +108,21 @@ extern_prod_order_t_schema: dict[str, type[pl.DataType]] = { "Fertigware aus Nähband": pl.UInt64, "Teile kontrolliert": pl.UInt64, "Teile verpackt in Karton": pl.UInt64, - "Anzahl Bänder": pl.UInt16, - "Anzahl Näher": pl.UInt16, + "Anzahl Bänder": pl.UInt32, + "Anzahl Näher": pl.UInt32, "Arbeitsstunden pro Näher": pl.UInt8, "Anzahl Arbeitstage pro Woche": pl.UInt8, "Blockauftrag": pl.String, } +extern_MIS_t_schema: dict[str, type[pl.DataType]] = { + "PA": pl.UInt64, + "PA Pos": pl.UInt32, + "VK Auftrag": pl.UInt64, + "Konfektionär": pl.String, + "Lieferantnr.": pl.UInt64, +} + # ** write extern_results_prod_orders_t: Table = Table( "KPI_PRODUKTIONSAUFTRAEGE", @@ -136,6 +145,7 @@ extern_results_suppliers_t: Table = Table( Column("ID", sql.Integer, primary_key=True), Column("AKTUALISIERT_AM", sql.DateTime, nullable=False), Column("KONFEKTIONAER", sql.String(200), nullable=True), + Column("KONFEKTIONAER_ID", sql.Integer, nullable=True), Column("QUOTE_ERSTBESTAETIGUNG", sql.Numeric(7, 4), nullable=True), Column("PROZENT_LIEFERTREUE", sql.Numeric(7, 4), nullable=True), Column("ANTEIL_PROZENT_LIEFERTERMINUNTERSCHREITUNG", sql.Numeric(7, 4), nullable=True),