Added new excel converter for container rates

This commit is contained in:
Jan 2025-09-26 20:35:39 +02:00
parent 78a6d1ef7e
commit 12e2abf6f9

View file

@ -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()