From 12e2abf6f95032ee27b44da895e2f454aed2afbf Mon Sep 17 00:00:00 2001 From: Jan Date: Fri, 26 Sep 2025 20:35:39 +0200 Subject: [PATCH] Added new excel converter for container rates --- ...xcel_export__container_rate_sql_extract.py | 210 ++++++++++++++++++ 1 file changed, 210 insertions(+) create mode 100644 src/main/resources/master_data/08-excel_export__container_rate_sql_extract.py diff --git a/src/main/resources/master_data/08-excel_export__container_rate_sql_extract.py b/src/main/resources/master_data/08-excel_export__container_rate_sql_extract.py new file mode 100644 index 0000000..824d477 --- /dev/null +++ b/src/main/resources/master_data/08-excel_export__container_rate_sql_extract.py @@ -0,0 +1,210 @@ +#!/usr/bin/env python3 +""" +Excel zu SQL Konverter für Container Rates +Konvertiert Excel-Datei mit Container-Raten in SQL INSERT-Statements +Angepasst für neues Excel-Format mit allen Raten in einer Zeile +""" + +import pandas as pd +import sys +from pathlib import Path + +def load_excel_data(file_path): + """ + Lädt die Excel-Datei und gibt die Daten als DataFrame zurück + """ + try: + # Lade das Sheet "Container Rate" (falls mehrere Sheets vorhanden sind) + df = pd.read_excel(file_path, sheet_name='Container Rate') + print(f"✓ Excel-Datei geladen: {len(df)} Zeilen") + return df + except Exception as e: + # Falls kein Sheet "Container Rate" existiert, lade das erste Sheet + try: + df = pd.read_excel(file_path) + print(f"✓ Excel-Datei geladen: {len(df)} Zeilen") + return df + except Exception as e2: + print(f"✗ Fehler beim Laden der Excel-Datei: {e2}") + sys.exit(1) + +def process_data(df): + """ + Verarbeitet die Daten und erstellt SQL INSERT-Statements + Neues Format: Alle Raten sind bereits in einer Zeile + """ + sql_statements = [] + + # Mapping der Spaltennamen (neues Format -> erwartete Variablen) + column_mapping = { + 'Origin': 'from_port', + 'Destination': 'to_port', + 'Transport mode': 'transport_type', + 'Rate 20 ft GP [EUR]': 'rate_teu', + 'Rate 40 ft GP [EUR]': 'rate_feu', + 'Rate 40 ft HC [EUR]': 'rate_hc', + 'Lead time [d]': 'lead_time' + } + + # Prüfe ob alle erforderlichen Spalten vorhanden sind + missing_columns = [] + for expected_col in column_mapping.keys(): + if expected_col not in df.columns: + missing_columns.append(expected_col) + + if missing_columns: + print(f"✗ Fehlende Spalten in Excel-Datei: {missing_columns}") + print(f" Vorhandene Spalten: {list(df.columns)}") + sys.exit(1) + + # Iteriere über alle Zeilen + for index, row in df.iterrows(): + # Extrahiere Werte aus der Zeile + from_port = row['Origin'] + to_port = row['Destination'] + transport_type = row['Transport mode'] + + # Raten verarbeiten - NULL wenn NaN oder leer + rate_teu = row['Rate 20 ft GP [EUR]'] + rate_feu = row['Rate 40 ft GP [EUR]'] + rate_hc = row['Rate 40 ft HC [EUR]'] + lead_time = row['Lead time [d]'] + + # Formatiere Raten (NULL oder formatierte Zahl) + if pd.isna(rate_teu) or rate_teu == '': + rate_teu_sql = 'NULL' + else: + rate_teu_sql = f"{float(rate_teu):.2f}" + + if pd.isna(rate_feu) or rate_feu == '': + rate_feu_sql = 'NULL' + else: + rate_feu_sql = f"{float(rate_feu):.2f}" + + if pd.isna(rate_hc) or rate_hc == '': + rate_hc_sql = 'NULL' + else: + rate_hc_sql = f"{float(rate_hc):.2f}" + + if pd.isna(lead_time) or lead_time == '': + lead_time_sql = 'NULL' + else: + lead_time_sql = str(int(lead_time)) + + # SQL INSERT Statement erstellen + sql_statement = f"""INSERT INTO container_rate ( + from_node_id, + to_node_id, + container_rate_type, + rate_teu, + rate_feu, + rate_hc, + lead_time, + validity_period_id +) VALUES ( + (SELECT id FROM node WHERE external_mapping_id = '{from_port}'), + (SELECT id FROM node WHERE external_mapping_id = '{to_port}'), + '{transport_type}', + {rate_teu_sql}, + {rate_feu_sql}, + {rate_hc_sql}, + {lead_time_sql}, + @validity_period_id + );""" + + sql_statements.append(sql_statement) + + return sql_statements + +def write_sql_file(sql_statements, output_file): + """ + Schreibt die SQL-Statements in eine Datei + """ + try: + with open(output_file, 'w', encoding='utf-8') as f: + # Header schreiben + f.write("-- Container Rate INSERT Statements\n") + f.write("-- Generiert aus Excel-Datei (Neues Format)\n") + f.write("-- Alle Raten in einer Zeile pro Route\n\n") + + # Validity Period Variable setzen (falls noch nicht gesetzt) + f.write("-- Setze validity_period_id Variable (falls noch nicht gesetzt)\n") + f.write("SET @validity_period_id = 1;\n\n") + + # SQL Statements schreiben + for statement in sql_statements: + f.write(statement) + f.write("\n\n") + + print(f"✓ SQL-Datei erstellt: {output_file}") + print(f"✓ {len(sql_statements)} INSERT-Statements generiert") + + except Exception as e: + print(f"✗ Fehler beim Schreiben der SQL-Datei: {e}") + sys.exit(1) + +def main(): + """ + Hauptfunktion + """ + # Dateipfade - kann angepasst werden + excel_file = "lcc_export_export_container_rate.xlsx" # Neuer Dateiname + sql_file = "08-data-containerrate.sql" + + # Kommandozeilen-Argumente verarbeiten (optional) + if len(sys.argv) > 1: + excel_file = sys.argv[1] + if len(sys.argv) > 2: + sql_file = sys.argv[2] + + # Prüfen ob Excel-Datei existiert + if not Path(excel_file).exists(): + print(f"✗ Excel-Datei nicht gefunden: {excel_file}") + print("Bitte stellen Sie sicher, dass die Datei im aktuellen Verzeichnis liegt.") + print("\nVerwendung:") + print(f" python {sys.argv[0]} [excel_datei] [sql_ausgabe_datei]") + print(f"\nStandard:") + print(f" Excel-Datei: lcc_export_export_container_rate.xlsx") + print(f" SQL-Datei: 08-data-containerrate.sql") + sys.exit(1) + + print("Container Rates Excel zu SQL Konverter") + print("=" * 40) + print(f"Excel-Datei: {excel_file}") + print(f"SQL-Ausgabe: {sql_file}\n") + + # 1. Excel-Datei laden + df = load_excel_data(excel_file) + + # 2. Datenstruktur anzeigen + print(f"\n📊 Datenübersicht:") + print(f" Spalten: {list(df.columns)}") + print(f" Eindeutige Ursprungsorte: {df['Origin'].nunique()}") + print(f" Eindeutige Zielorte: {df['Destination'].nunique()}") + + # Transport-Modi anzeigen + transport_modes = df['Transport mode'].unique() + print(f" Transport-Modi: {transport_modes}") + + # Statistiken zu Raten + print(f"\n💰 Raten-Statistiken:") + print(f" 20 ft GP: {df['Rate 20 ft GP [EUR]'].count()} von {len(df)} Einträgen") + print(f" 40 ft GP: {df['Rate 40 ft GP [EUR]'].count()} von {len(df)} Einträgen") + print(f" 40 ft HC: {df['Rate 40 ft HC [EUR]'].count()} von {len(df)} Einträgen") + + # Lead Time Statistiken + lead_times = df['Lead time [d]'].dropna().unique() + print(f"\n⏱️ Lead Times (Tage): {sorted(lead_times)}") + + # 3. Daten verarbeiten und SQL-Statements erstellen + print("\n⚙️ Verarbeite Daten...") + sql_statements = process_data(df) + + # 4. SQL-Datei schreiben + write_sql_file(sql_statements, sql_file) + + print(f"\n✅ Fertig! SQL-Datei wurde erstellt: {sql_file}") + print(f"\n💡 Hinweis: Vergessen Sie nicht, @validity_period_id vor dem Ausführen zu setzen!") + +if __name__ == "__main__": + main() \ No newline at end of file