"Add emergency backup and update fullcalendar scripts"
This commit is contained in:
@@ -1823,6 +1823,7 @@ def api_admin_system_health():
|
|||||||
|
|
||||||
@app.route("/api/admin/fix-errors", methods=['POST'])
|
@app.route("/api/admin/fix-errors", methods=['POST'])
|
||||||
@login_required
|
@login_required
|
||||||
|
@csrf.exempt
|
||||||
def api_admin_fix_errors():
|
def api_admin_fix_errors():
|
||||||
"""API-Endpunkt um automatische Fehler-Reparatur auszuführen."""
|
"""API-Endpunkt um automatische Fehler-Reparatur auszuführen."""
|
||||||
if not current_user.is_admin:
|
if not current_user.is_admin:
|
||||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
backend/app/database/myp.db.emergency_backup_20250529_185111
Normal file
BIN
backend/app/database/myp.db.emergency_backup_20250529_185111
Normal file
Binary file not shown.
226
backend/app/quick_fix.py
Normal file
226
backend/app/quick_fix.py
Normal file
@@ -0,0 +1,226 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Schnelle Datenbank-Reparatur für kritische Fehler
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sqlite3
|
||||||
|
import os
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
# Datenbankpfad
|
||||||
|
DATABASE_PATH = "database/myp.db"
|
||||||
|
|
||||||
|
def quick_fix_database():
|
||||||
|
"""Behebt die kritischsten Datenbankprobleme sofort"""
|
||||||
|
print("🔧 Starte schnelle Datenbank-Reparatur...")
|
||||||
|
|
||||||
|
if not os.path.exists(DATABASE_PATH):
|
||||||
|
print(f"❌ Datenbankdatei nicht gefunden: {DATABASE_PATH}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Backup erstellen
|
||||||
|
backup_path = f"{DATABASE_PATH}.emergency_backup_{datetime.now().strftime('%Y%m%d_%H%M%S')}"
|
||||||
|
import shutil
|
||||||
|
shutil.copy2(DATABASE_PATH, backup_path)
|
||||||
|
print(f"✅ Emergency-Backup erstellt: {backup_path}")
|
||||||
|
|
||||||
|
# Verbindung zur Datenbank
|
||||||
|
conn = sqlite3.connect(DATABASE_PATH)
|
||||||
|
cursor = conn.cursor()
|
||||||
|
|
||||||
|
print("🔧 Repariere Datenbank-Schema...")
|
||||||
|
|
||||||
|
# 1. Fehlende Spalte duration_minutes zu guest_requests hinzufügen
|
||||||
|
try:
|
||||||
|
cursor.execute("ALTER TABLE guest_requests ADD COLUMN duration_minutes INTEGER")
|
||||||
|
print("✅ Spalte duration_minutes zu guest_requests hinzugefügt")
|
||||||
|
except sqlite3.OperationalError as e:
|
||||||
|
if "duplicate column name" in str(e).lower():
|
||||||
|
print("ℹ️ Spalte duration_minutes bereits vorhanden")
|
||||||
|
else:
|
||||||
|
print(f"⚠️ Fehler bei duration_minutes: {e}")
|
||||||
|
|
||||||
|
# 2. Fehlende Spalten zu users hinzufügen
|
||||||
|
user_columns = [
|
||||||
|
("username", "VARCHAR(100) UNIQUE"),
|
||||||
|
("updated_at", "DATETIME DEFAULT CURRENT_TIMESTAMP"),
|
||||||
|
("department", "VARCHAR(100)"),
|
||||||
|
("position", "VARCHAR(100)"),
|
||||||
|
("phone", "VARCHAR(50)"),
|
||||||
|
("bio", "TEXT")
|
||||||
|
]
|
||||||
|
|
||||||
|
for column_name, column_def in user_columns:
|
||||||
|
try:
|
||||||
|
cursor.execute(f"ALTER TABLE users ADD COLUMN {column_name} {column_def}")
|
||||||
|
print(f"✅ Spalte {column_name} zu users hinzugefügt")
|
||||||
|
except sqlite3.OperationalError as e:
|
||||||
|
if "duplicate column name" in str(e).lower():
|
||||||
|
print(f"ℹ️ Spalte {column_name} bereits vorhanden")
|
||||||
|
else:
|
||||||
|
print(f"⚠️ Fehler bei {column_name}: {e}")
|
||||||
|
|
||||||
|
# 3. Fehlende Spalten zu printers hinzufügen
|
||||||
|
printer_columns = [
|
||||||
|
("plug_username", "VARCHAR(100) DEFAULT 'admin'"),
|
||||||
|
("plug_password", "VARCHAR(100) DEFAULT 'admin'"),
|
||||||
|
("last_checked", "DATETIME")
|
||||||
|
]
|
||||||
|
|
||||||
|
for column_name, column_def in printer_columns:
|
||||||
|
try:
|
||||||
|
cursor.execute(f"ALTER TABLE printers ADD COLUMN {column_name} {column_def}")
|
||||||
|
print(f"✅ Spalte {column_name} zu printers hinzugefügt")
|
||||||
|
except sqlite3.OperationalError as e:
|
||||||
|
if "duplicate column name" in str(e).lower():
|
||||||
|
print(f"ℹ️ Spalte {column_name} bereits vorhanden")
|
||||||
|
else:
|
||||||
|
print(f"⚠️ Fehler bei {column_name}: {e}")
|
||||||
|
|
||||||
|
# 4. Username für bestehende User setzen (falls NULL)
|
||||||
|
try:
|
||||||
|
cursor.execute("UPDATE users SET username = email WHERE username IS NULL")
|
||||||
|
updated_users = cursor.rowcount
|
||||||
|
if updated_users > 0:
|
||||||
|
print(f"✅ Username für {updated_users} Benutzer gesetzt")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"⚠️ Fehler beim Setzen der Usernames: {e}")
|
||||||
|
|
||||||
|
# 5. Drucker-Daten nachtragen
|
||||||
|
print("🖨️ Trage Drucker nach...")
|
||||||
|
|
||||||
|
# Prüfen ob bereits Drucker vorhanden sind
|
||||||
|
cursor.execute("SELECT COUNT(*) FROM printers")
|
||||||
|
printer_count = cursor.fetchone()[0]
|
||||||
|
|
||||||
|
if printer_count == 0:
|
||||||
|
# Standard-Drucker hinzufügen
|
||||||
|
printers_to_add = [
|
||||||
|
{
|
||||||
|
'name': 'Printer 1',
|
||||||
|
'model': 'P115',
|
||||||
|
'location': 'Werk 040 - Berlin - TBA',
|
||||||
|
'ip_address': '192.168.0.100',
|
||||||
|
'mac_address': '98:254A:E1:2001',
|
||||||
|
'plug_ip': '192.168.0.100',
|
||||||
|
'plug_username': 'admin',
|
||||||
|
'plug_password': 'admin',
|
||||||
|
'status': 'offline',
|
||||||
|
'active': 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'name': 'Printer 2',
|
||||||
|
'model': 'P115',
|
||||||
|
'location': 'Werk 040 - Berlin - TBA',
|
||||||
|
'ip_address': '192.168.0.101',
|
||||||
|
'mac_address': '98:254A:E1:2002',
|
||||||
|
'plug_ip': '192.168.0.101',
|
||||||
|
'plug_username': 'admin',
|
||||||
|
'plug_password': 'admin',
|
||||||
|
'status': 'offline',
|
||||||
|
'active': 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'name': 'Printer 3',
|
||||||
|
'model': 'P115',
|
||||||
|
'location': 'Werk 040 - Berlin - TBA',
|
||||||
|
'ip_address': '192.168.0.102',
|
||||||
|
'mac_address': '98:254A:E1:2003',
|
||||||
|
'plug_ip': '192.168.0.102',
|
||||||
|
'plug_username': 'admin',
|
||||||
|
'plug_password': 'admin',
|
||||||
|
'status': 'offline',
|
||||||
|
'active': 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'name': 'Printer 4',
|
||||||
|
'model': 'P115',
|
||||||
|
'location': 'Werk 040 - Berlin - TBA',
|
||||||
|
'ip_address': '192.168.0.103',
|
||||||
|
'mac_address': '98:254A:E1:2004',
|
||||||
|
'plug_ip': '192.168.0.103',
|
||||||
|
'plug_username': 'admin',
|
||||||
|
'plug_password': 'admin',
|
||||||
|
'status': 'offline',
|
||||||
|
'active': 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'name': 'Printer 5',
|
||||||
|
'model': 'P115',
|
||||||
|
'location': 'Werk 040 - Berlin - TBA',
|
||||||
|
'ip_address': '192.168.0.104',
|
||||||
|
'mac_address': '98:254A:E1:2005',
|
||||||
|
'plug_ip': '192.168.0.104',
|
||||||
|
'plug_username': 'admin',
|
||||||
|
'plug_password': 'admin',
|
||||||
|
'status': 'offline',
|
||||||
|
'active': 1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
'name': 'Printer 6',
|
||||||
|
'model': 'P115',
|
||||||
|
'location': 'Werk 040 - Berlin - TBA',
|
||||||
|
'ip_address': '192.168.0.106',
|
||||||
|
'mac_address': '98:254A:E1:2006',
|
||||||
|
'plug_ip': '192.168.0.106',
|
||||||
|
'plug_username': 'admin',
|
||||||
|
'plug_password': 'admin',
|
||||||
|
'status': 'offline',
|
||||||
|
'active': 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
for printer in printers_to_add:
|
||||||
|
try:
|
||||||
|
cursor.execute("""
|
||||||
|
INSERT INTO printers (name, model, location, ip_address, mac_address, plug_ip, plug_username, plug_password, status, active, created_at)
|
||||||
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
|
""", (
|
||||||
|
printer['name'], printer['model'], printer['location'],
|
||||||
|
printer['ip_address'], printer['mac_address'], printer['plug_ip'],
|
||||||
|
printer['plug_username'], printer['plug_password'],
|
||||||
|
printer['status'], printer['active'], datetime.now()
|
||||||
|
))
|
||||||
|
print(f"✅ Drucker {printer['name']} hinzugefügt")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"⚠️ Fehler beim Hinzufügen von {printer['name']}: {e}")
|
||||||
|
else:
|
||||||
|
print(f"ℹ️ {printer_count} Drucker bereits vorhanden")
|
||||||
|
|
||||||
|
# 6. Optimierungen
|
||||||
|
print("🔧 Führe Datenbankoptimierungen durch...")
|
||||||
|
try:
|
||||||
|
# Indizes erstellen
|
||||||
|
indices = [
|
||||||
|
"CREATE INDEX IF NOT EXISTS idx_users_email ON users(email)",
|
||||||
|
"CREATE INDEX IF NOT EXISTS idx_users_username ON users(username)",
|
||||||
|
"CREATE INDEX IF NOT EXISTS idx_jobs_user_id ON jobs(user_id)",
|
||||||
|
"CREATE INDEX IF NOT EXISTS idx_jobs_printer_id ON jobs(printer_id)",
|
||||||
|
"CREATE INDEX IF NOT EXISTS idx_jobs_status ON jobs(status)",
|
||||||
|
"CREATE INDEX IF NOT EXISTS idx_guest_requests_status ON guest_requests(status)"
|
||||||
|
]
|
||||||
|
|
||||||
|
for index_sql in indices:
|
||||||
|
cursor.execute(index_sql)
|
||||||
|
|
||||||
|
# Statistiken aktualisieren
|
||||||
|
cursor.execute("ANALYZE")
|
||||||
|
print("✅ Datenbankoptimierungen abgeschlossen")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"⚠️ Fehler bei Optimierungen: {e}")
|
||||||
|
|
||||||
|
# Änderungen speichern
|
||||||
|
conn.commit()
|
||||||
|
conn.close()
|
||||||
|
|
||||||
|
print("✅ Schnelle Datenbank-Reparatur erfolgreich abgeschlossen!")
|
||||||
|
return True
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ Kritischer Fehler bei der Reparatur: {str(e)}")
|
||||||
|
return False
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
quick_fix_database()
|
6
backend/app/static/js/fullcalendar/interaction.min.js
vendored
Normal file
6
backend/app/static/js/fullcalendar/interaction.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
6
backend/app/static/js/fullcalendar/list.min.js
vendored
Normal file
6
backend/app/static/js/fullcalendar/list.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
6
backend/app/static/js/fullcalendar/timegrid.min.js
vendored
Normal file
6
backend/app/static/js/fullcalendar/timegrid.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
@@ -648,7 +648,11 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
||||||
<!-- FullCalendar JS -->
|
<!-- FullCalendar JS -->
|
||||||
<script src="{{ url_for('static', filename='js/fullcalendar/main.min.js') }}"></script>
|
<script src="{{ url_for('static', filename='js/fullcalendar/core.min.js') }}"></script>
|
||||||
|
<script src="{{ url_for('static', filename='js/fullcalendar/daygrid.min.js') }}"></script>
|
||||||
|
<script src="{{ url_for('static', filename='js/fullcalendar/timegrid.min.js') }}"></script>
|
||||||
|
<script src="{{ url_for('static', filename='js/fullcalendar/interaction.min.js') }}"></script>
|
||||||
|
<script src="{{ url_for('static', filename='js/fullcalendar/list.min.js') }}"></script>
|
||||||
<input type="hidden" id="canEditFlag" value="{% if can_edit %}true{% else %}false{% endif %}">
|
<input type="hidden" id="canEditFlag" value="{% if can_edit %}true{% else %}false{% endif %}">
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
|
Reference in New Issue
Block a user