Projektarbeit-MYP/backend/app/migrate_db.py

162 lines
6.9 KiB
Python

#!/usr/bin/env python3.11
"""
Datenbank-Migrationsskript für MYP Platform
Dieses Skript führt notwendige Änderungen an der Datenbankstruktur durch,
um sie mit den neuesten Modellen kompatibel zu machen.
"""
import sqlite3
import os
from datetime import datetime
from config.settings import DATABASE_PATH, ensure_database_directory
def migrate_database():
"""Führt alle notwendigen Datenbankmigrationen durch."""
ensure_database_directory()
if not os.path.exists(DATABASE_PATH):
print("Datenbank existiert nicht. Führe init_db.py aus, um sie zu erstellen.")
return False
conn = sqlite3.connect(DATABASE_PATH)
cursor = conn.cursor()
print("Starte Datenbankmigration...")
try:
# Migration 1: Füge username-Feld zu users-Tabelle hinzu
try:
cursor.execute("ALTER TABLE users ADD COLUMN username VARCHAR(100)")
print("✓ Username-Feld zur users-Tabelle hinzugefügt")
except sqlite3.OperationalError as e:
if "duplicate column name" in str(e).lower():
print("✓ Username-Feld bereits vorhanden")
else:
raise e
# Migration 2: Füge active-Feld zu users-Tabelle hinzu
try:
cursor.execute("ALTER TABLE users ADD COLUMN active BOOLEAN DEFAULT 1")
print("✓ Active-Feld zur users-Tabelle hinzugefügt")
except sqlite3.OperationalError as e:
if "duplicate column name" in str(e).lower():
print("✓ Active-Feld bereits vorhanden")
else:
raise e
# Migration 3: Setze username für bestehende Benutzer
cursor.execute("SELECT id, email, username FROM users WHERE username IS NULL OR username = ''")
users_without_username = cursor.fetchall()
for user_id, email, username in users_without_username:
if not username:
# Generiere username aus email (Teil vor @)
new_username = email.split('@')[0] if '@' in email else f"user_{user_id}"
cursor.execute("UPDATE users SET username = ? WHERE id = ?", (new_username, user_id))
print(f"✓ Username '{new_username}' für Benutzer {email} gesetzt")
# Migration 3.5: Füge last_login-Feld zu users-Tabelle hinzu
try:
cursor.execute("ALTER TABLE users ADD COLUMN last_login DATETIME")
print("✓ Last_login-Feld zur users-Tabelle hinzugefügt")
except sqlite3.OperationalError as e:
if "duplicate column name" in str(e).lower():
print("✓ Last_login-Feld bereits vorhanden")
else:
raise e
# Migration 4: Prüfe und korrigiere Job-Tabelle falls nötig
try:
# Prüfe ob die Tabelle die neuen Felder hat
cursor.execute("PRAGMA table_info(jobs)")
columns = [row[1] for row in cursor.fetchall()]
if 'duration_minutes' not in columns:
cursor.execute("ALTER TABLE jobs ADD COLUMN duration_minutes INTEGER")
print("✓ Duration_minutes-Feld zur jobs-Tabelle hinzugefügt")
# Setze Standardwerte für bestehende Jobs (60 Minuten)
cursor.execute("UPDATE jobs SET duration_minutes = 60 WHERE duration_minutes IS NULL")
print("✓ Standardwerte für duration_minutes gesetzt")
# Prüfe ob title zu name umbenannt werden muss
if 'title' in columns and 'name' not in columns:
# SQLite unterstützt kein direktes Umbenennen von Spalten
# Wir müssen die Tabelle neu erstellen
print("⚠ Konvertierung von 'title' zu 'name' in jobs-Tabelle...")
# Backup der Daten
cursor.execute("""
CREATE TABLE jobs_backup AS
SELECT * FROM jobs
""")
# Lösche alte Tabelle
cursor.execute("DROP TABLE jobs")
# Erstelle neue Tabelle mit korrekter Struktur
cursor.execute("""
CREATE TABLE jobs (
id INTEGER PRIMARY KEY,
name VARCHAR(200) NOT NULL,
description VARCHAR(500),
user_id INTEGER NOT NULL,
printer_id INTEGER NOT NULL,
start_at DATETIME,
end_at DATETIME,
actual_end_time DATETIME,
status VARCHAR(20) DEFAULT 'scheduled',
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
notes VARCHAR(500),
material_used FLOAT,
file_path VARCHAR(500),
owner_id INTEGER,
duration_minutes INTEGER NOT NULL DEFAULT 60,
FOREIGN KEY (user_id) REFERENCES users(id),
FOREIGN KEY (printer_id) REFERENCES printers(id),
FOREIGN KEY (owner_id) REFERENCES users(id)
)
""")
# Daten zurückkopieren (title -> name)
cursor.execute("""
INSERT INTO jobs (
id, name, description, user_id, printer_id, start_at, end_at,
actual_end_time, status, created_at, notes, material_used,
file_path, owner_id, duration_minutes
)
SELECT
id, title, description, user_id, printer_id, start_at, end_at,
actual_end_time, status, created_at, notes, material_used,
file_path, owner_id, COALESCE(duration_minutes, 60)
FROM jobs_backup
""")
# Backup-Tabelle löschen
cursor.execute("DROP TABLE jobs_backup")
print("✓ Jobs-Tabelle erfolgreich konvertiert")
except sqlite3.OperationalError as e:
print(f"⚠ Fehler bei Job-Tabellen-Migration: {e}")
# Änderungen speichern
conn.commit()
print("\n✅ Datenbankmigration erfolgreich abgeschlossen!")
return True
except Exception as e:
print(f"\n❌ Fehler bei der Migration: {e}")
conn.rollback()
return False
finally:
conn.close()
if __name__ == "__main__":
success = migrate_database()
if success:
print("\nDie Datenbank wurde erfolgreich migriert.")
print("Sie können nun die Anwendung starten: python3.11 app.py")
else:
print("\nMigration fehlgeschlagen. Bitte überprüfen Sie die Fehlermeldungen.")