🐛 Backend Documentation Fix for Button Reservation Creation Issue & Undefined Jobs Problem 🖥️📚
This commit is contained in:
1
backend/DOCS/BUTTON_RESERVIERUNG_ERSTELLEN_FIX.md
Normal file
1
backend/DOCS/BUTTON_RESERVIERUNG_ERSTELLEN_FIX.md
Normal file
@ -0,0 +1 @@
|
||||
|
1
backend/DOCS/UNDEFINED_JOBS_PROBLEM_LÖSUNG.md
Normal file
1
backend/DOCS/UNDEFINED_JOBS_PROBLEM_LÖSUNG.md
Normal file
@ -0,0 +1 @@
|
||||
|
Binary file not shown.
178
backend/app.py
178
backend/app.py
@ -949,8 +949,182 @@ def index():
|
||||
@app.route("/dashboard")
|
||||
@login_required
|
||||
def dashboard():
|
||||
"""Haupt-Dashboard"""
|
||||
return render_template("dashboard.html")
|
||||
"""Haupt-Dashboard mit vollständigen Daten für die Anzeige"""
|
||||
try:
|
||||
from models import get_db_session, Job, Printer, User
|
||||
from datetime import datetime, timedelta
|
||||
|
||||
db_session = get_db_session()
|
||||
|
||||
# ===== AKTIVE JOBS LADEN =====
|
||||
active_jobs_query = db_session.query(Job).filter(
|
||||
Job.status.in_(['scheduled', 'running', 'printing', 'pending'])
|
||||
)
|
||||
|
||||
# Normale Benutzer sehen nur ihre eigenen Jobs
|
||||
if not current_user.is_admin:
|
||||
active_jobs_query = active_jobs_query.filter(Job.user_id == current_user.id)
|
||||
|
||||
active_jobs = active_jobs_query.order_by(Job.created_at.desc()).limit(10).all()
|
||||
|
||||
# ===== DRUCKER-DATEN LADEN =====
|
||||
printers = db_session.query(Printer).filter(Printer.active == True).all()
|
||||
|
||||
# ===== STATISTIKEN BERECHNEN =====
|
||||
# Aktive Jobs zählen
|
||||
active_jobs_count = len(active_jobs)
|
||||
|
||||
# Verfügbare Drucker zählen
|
||||
available_printers_count = len([p for p in printers if p.status in ['idle', 'ready']])
|
||||
|
||||
# Gesamtanzahl Jobs (benutzerabhängig)
|
||||
if current_user.is_admin:
|
||||
total_jobs_count = db_session.query(Job).count()
|
||||
completed_jobs_count = db_session.query(Job).filter(Job.status == 'completed').count()
|
||||
else:
|
||||
total_jobs_count = db_session.query(Job).filter(Job.user_id == current_user.id).count()
|
||||
completed_jobs_count = db_session.query(Job).filter(
|
||||
Job.user_id == current_user.id,
|
||||
Job.status == 'completed'
|
||||
).count()
|
||||
|
||||
# Erfolgsrate berechnen
|
||||
success_rate = round((completed_jobs_count / total_jobs_count * 100), 1) if total_jobs_count > 0 else 0
|
||||
|
||||
# ===== AKTIVE JOBS FÜR DASHBOARD FORMATIEREN =====
|
||||
dashboard_active_jobs = []
|
||||
for job in active_jobs:
|
||||
job_dict = job.to_dict() # Nutzt die erweiterte to_dict Methode
|
||||
|
||||
# Zusätzliche Dashboard-spezifische Felder
|
||||
job_dict.update({
|
||||
'id': job.id,
|
||||
'name': job.name or f"Job #{job.id}",
|
||||
'printer': job.printer.name if job.printer else "Unbekannter Drucker",
|
||||
'start_time': job.start_at.strftime('%d.%m.%Y %H:%M') if job.start_at else "Nicht festgelegt",
|
||||
'status_text': job._get_status_text(job.status),
|
||||
'progress': job._calculate_progress(),
|
||||
'file_name': job.name # Für Template-Kompatibilität
|
||||
})
|
||||
|
||||
dashboard_active_jobs.append(job_dict)
|
||||
|
||||
# ===== DRUCKER FÜR DASHBOARD FORMATIEREN =====
|
||||
dashboard_printers = []
|
||||
for printer in printers:
|
||||
printer_dict = printer.to_dict()
|
||||
|
||||
# Status-Icon und -Farbe bestimmen
|
||||
status_mapping = {
|
||||
'online': {'icon': 'fas fa-check-circle', 'color': 'text-green-500'},
|
||||
'idle': {'icon': 'fas fa-check-circle', 'color': 'text-green-500'},
|
||||
'busy': {'icon': 'fas fa-clock', 'color': 'text-yellow-500'},
|
||||
'offline': {'icon': 'fas fa-times-circle', 'color': 'text-red-500'},
|
||||
'error': {'icon': 'fas fa-exclamation-triangle', 'color': 'text-red-500'}
|
||||
}
|
||||
|
||||
status_info = status_mapping.get(printer.status, status_mapping['offline'])
|
||||
printer_dict.update({
|
||||
'status_icon': status_info['icon'],
|
||||
'status_color': status_info['color'],
|
||||
'is_available': printer.status in ['idle', 'online', 'ready']
|
||||
})
|
||||
|
||||
dashboard_printers.append(printer_dict)
|
||||
|
||||
# ===== LETZTE AKTIVITÄTEN =====
|
||||
# Letzte Jobs als Aktivitäten
|
||||
recent_jobs = db_session.query(Job).filter(
|
||||
Job.user_id == current_user.id if not current_user.is_admin else True
|
||||
).order_by(Job.updated_at.desc()).limit(5).all()
|
||||
|
||||
activities = []
|
||||
for job in recent_jobs:
|
||||
time_diff = datetime.now() - (job.updated_at or job.created_at)
|
||||
if time_diff.days == 0:
|
||||
if time_diff.seconds < 3600:
|
||||
time_str = f"vor {time_diff.seconds // 60} Minuten"
|
||||
else:
|
||||
time_str = f"vor {time_diff.seconds // 3600} Stunden"
|
||||
else:
|
||||
time_str = f"vor {time_diff.days} Tagen"
|
||||
|
||||
activities.append({
|
||||
'description': f"Job '{job.name}' - Status: {job._get_status_text(job.status)}",
|
||||
'time': time_str
|
||||
})
|
||||
|
||||
# ===== TRENDS BERECHNEN (optional) =====
|
||||
yesterday = datetime.now() - timedelta(days=1)
|
||||
week_ago = datetime.now() - timedelta(days=7)
|
||||
|
||||
# Jobs von heute vs. gestern
|
||||
jobs_today = db_session.query(Job).filter(
|
||||
Job.created_at >= datetime.now().replace(hour=0, minute=0, second=0)
|
||||
).count()
|
||||
jobs_yesterday = db_session.query(Job).filter(
|
||||
Job.created_at >= yesterday.replace(hour=0, minute=0, second=0),
|
||||
Job.created_at < datetime.now().replace(hour=0, minute=0, second=0)
|
||||
).count()
|
||||
|
||||
active_jobs_trend = None
|
||||
if jobs_yesterday > 0:
|
||||
trend_percent = round(((jobs_today - jobs_yesterday) / jobs_yesterday) * 100, 1)
|
||||
active_jobs_trend = {
|
||||
'value': trend_percent,
|
||||
'direction': 'up' if trend_percent > 0 else 'down' if trend_percent < 0 else 'stable'
|
||||
}
|
||||
|
||||
db_session.close()
|
||||
|
||||
# ===== TEMPLATE-DATEN ZUSAMMENSTELLEN =====
|
||||
template_data = {
|
||||
# Statistiken
|
||||
'active_jobs_count': active_jobs_count,
|
||||
'available_printers_count': available_printers_count,
|
||||
'total_jobs_count': total_jobs_count,
|
||||
'success_rate': success_rate,
|
||||
|
||||
# Trends
|
||||
'active_jobs_trend': active_jobs_trend,
|
||||
'printer_availability_trend': None, # Kann später implementiert werden
|
||||
'total_jobs_trend': None,
|
||||
'success_rate_trend': None,
|
||||
|
||||
# Daten für Listen
|
||||
'active_jobs': dashboard_active_jobs,
|
||||
'printers': dashboard_printers,
|
||||
'activities': activities,
|
||||
|
||||
# Metadaten
|
||||
'last_updated': datetime.now().strftime('%d.%m.%Y %H:%M'),
|
||||
'user_name': current_user.name,
|
||||
'is_admin': current_user.is_admin
|
||||
}
|
||||
|
||||
app_logger.info(f"✅ Dashboard geladen für {current_user.name}: {active_jobs_count} aktive Jobs, {available_printers_count} verfügbare Drucker")
|
||||
|
||||
return render_template("dashboard.html", **template_data)
|
||||
|
||||
except Exception as e:
|
||||
app_logger.error(f"❌ Fehler beim Laden des Dashboards: {str(e)}", exc_info=True)
|
||||
|
||||
# Fallback-Dashboard mit minimalen Daten
|
||||
fallback_data = {
|
||||
'active_jobs_count': 0,
|
||||
'available_printers_count': 0,
|
||||
'total_jobs_count': 0,
|
||||
'success_rate': 0,
|
||||
'active_jobs': [],
|
||||
'printers': [],
|
||||
'activities': [],
|
||||
'error': f"Fehler beim Laden der Dashboard-Daten: {str(e)}",
|
||||
'last_updated': datetime.now().strftime('%d.%m.%Y %H:%M'),
|
||||
'user_name': current_user.name if current_user.is_authenticated else "Unbekannt",
|
||||
'is_admin': current_user.is_admin if current_user.is_authenticated else False
|
||||
}
|
||||
|
||||
return render_template("dashboard.html", **fallback_data)
|
||||
|
||||
@app.route("/csrf-test")
|
||||
def csrf_test_page():
|
||||
|
@ -64856,3 +64856,63 @@ WHERE users.role = ?]
|
||||
- C:\Users\TTOMCZA.EMEA\Dev\Projektarbeit-MYP\backend\templates
|
||||
-> found ('C:\\Users\\TTOMCZA.EMEA\\Dev\\Projektarbeit-MYP\\backend\\templates\\macros\\ui_components.html')
|
||||
2025-06-20 12:06:41 - [app] app - [DEBUG] DEBUG - Response:
|
||||
2025-06-20 12:06:44 - [app] app - [DEBUG] DEBUG - Request:
|
||||
2025-06-20 12:06:44 - [app] app - [DEBUG] DEBUG - Request:
|
||||
2025-06-20 12:06:44 - [app] app - [DEBUG] DEBUG - Response:
|
||||
2025-06-20 12:06:44 - [app] app - [DEBUG] DEBUG - Response:
|
||||
2025-06-20 12:07:07 - [app] app - [DEBUG] DEBUG - Request:
|
||||
2025-06-20 12:07:07 - [app] app - [DEBUG] DEBUG - Request:
|
||||
2025-06-20 12:07:07 - [app] app - [ERROR] ERROR - Fehler beim Laden des Benutzers :
|
||||
2025-06-20 12:07:07 - [app] app - [DEBUG] DEBUG - Response:
|
||||
2025-06-20 12:07:07 - [app] app - [DEBUG] DEBUG - Response:
|
||||
2025-06-20 12:07:07 - [app] app - [DEBUG] DEBUG - Request:
|
||||
2025-06-20 12:07:07 - [app] app - [DEBUG] DEBUG - Response:
|
||||
2025-06-20 12:07:07 - [app] app - [DEBUG] DEBUG - Request:
|
||||
2025-06-20 12:07:07 - [app] app - [DEBUG] DEBUG - Response:
|
||||
2025-06-20 12:07:07 - [app] app - [DEBUG] DEBUG - Request:
|
||||
2025-06-20 12:07:07 - [app] app - [DEBUG] DEBUG - Response:
|
||||
2025-06-20 12:07:14 - [app] app - [DEBUG] DEBUG - Request:
|
||||
2025-06-20 12:07:14 - [app] app - [DEBUG] DEBUG - Request:
|
||||
2025-06-20 12:07:14 - [app] app - [DEBUG] DEBUG - Response:
|
||||
2025-06-20 12:07:14 - [app] app - [DEBUG] DEBUG - Response:
|
||||
2025-06-20 12:07:22 - [app] app - [INFO] INFO - [SHUTDOWN] 🧹 Cleanup wird ausgeführt...
|
||||
2025-06-20 12:07:22 - [app] app - [INFO] INFO - [SHUTDOWN] ✅ Queue Manager gestoppt
|
||||
2025-06-20 12:07:22 - [app] app - [ERROR] ERROR - [SHUTDOWN] ❌ Cleanup-Fehler:
|
||||
2025-06-20 12:07:24 - [app] app - [INFO] INFO - Optimierte SQLite-Engine erstellt: database/myp.db
|
||||
2025-06-20 12:07:25 - [app] app - [INFO] INFO - [CONFIG] Erkannte Umgebung:
|
||||
2025-06-20 12:07:25 - [app] app - [INFO] INFO - [CONFIG] Production-Modus:
|
||||
2025-06-20 12:07:25 - [app] app - [INFO] INFO - [CONFIG] Verwende Development-Konfiguration
|
||||
2025-06-20 12:07:25 - [app] app - [INFO] INFO - [DEVELOPMENT] Aktiviere Development-Konfiguration
|
||||
2025-06-20 12:07:25 - [app] app - [INFO] INFO - [DEVELOPMENT] ✅ Konfiguration aktiviert
|
||||
2025-06-20 12:07:25 - [app] app - [INFO] INFO - [DEVELOPMENT] ✅ Environment:
|
||||
2025-06-20 12:07:25 - [app] app - [INFO] INFO - [DEVELOPMENT] ✅ Debug Mode:
|
||||
2025-06-20 12:07:25 - [app] app - [INFO] INFO - [DEVELOPMENT] ✅ SQL Echo:
|
||||
2025-06-20 12:07:25 - [app] app - [INFO] INFO - SQLite für Raspberry Pi optimiert (reduzierte Cache-Größe, SD-Karten I/O)
|
||||
2025-06-20 12:07:25 - [app] app - [INFO] INFO - Admin-Berechtigungen beim Start korrigiert: erstellt, aktualisiert
|
||||
2025-06-20 12:07:25 - [app] app - [INFO] INFO - [STARTUP] 🚀 Starte MYP -Umgebung
|
||||
2025-06-20 12:07:25 - [app] app - [INFO] INFO - [STARTUP] 🏢
|
||||
2025-06-20 12:07:25 - [app] app - [INFO] INFO - [STARTUP] 🔒 Air-Gapped:
|
||||
2025-06-20 12:07:25 - [app] app - [INFO] INFO - [STARTUP] Initialisiere Datenbank...
|
||||
2025-06-20 12:07:25 - [app] app - [INFO] INFO - Datenbank mit Optimierungen initialisiert
|
||||
2025-06-20 12:07:25 - [app] app - [INFO] INFO - [STARTUP] ✅ Datenbank initialisiert
|
||||
2025-06-20 12:07:25 - [app] app - [INFO] INFO - [STARTUP] Prüfe Initial-Admin...
|
||||
2025-06-20 12:07:25 - [app] app - [INFO] INFO - Admin-Benutzer admin (admin@mercedes-benz.com) existiert bereits. Passwort wurde zurückgesetzt.
|
||||
2025-06-20 12:07:25 - [app] app - [INFO] INFO - [STARTUP] ✅ Admin-Benutzer geprüft
|
||||
2025-06-20 12:07:25 - [app] app - [INFO] INFO - [STARTUP] Initialisiere statische Drucker...
|
||||
2025-06-20 12:07:25 - [app] app - [INFO] INFO - Drucker aktualisiert: Drucker 1 (192.168.0.100)
|
||||
2025-06-20 12:07:25 - [app] app - [INFO] INFO - Drucker aktualisiert: Drucker 2 (192.168.0.101)
|
||||
2025-06-20 12:07:25 - [app] app - [INFO] INFO - Drucker aktualisiert: Drucker 3 (192.168.0.102)
|
||||
2025-06-20 12:07:25 - [app] app - [INFO] INFO - Drucker aktualisiert: Drucker 4 (192.168.0.103)
|
||||
2025-06-20 12:07:25 - [app] app - [INFO] INFO - Drucker aktualisiert: Drucker 5 (192.168.0.104)
|
||||
2025-06-20 12:07:25 - [app] app - [INFO] INFO - Drucker aktualisiert: Drucker 6 (192.168.0.106)
|
||||
2025-06-20 12:07:25 - [app] app - [INFO] INFO - ✅ Statische Drucker-Initialisierung abgeschlossen: 0 erstellt, 6 aktualisiert
|
||||
2025-06-20 12:07:25 - [app] app - [INFO] INFO - 📍 Alle Drucker sind für Standort 'TBA Marienfelde' konfiguriert
|
||||
2025-06-20 12:07:25 - [app] app - [INFO] INFO - 🌐 IP-Bereich: 192.168.0.100-106 (außer .105)
|
||||
2025-06-20 12:07:25 - [app] app - [INFO] INFO - [STARTUP] ✅ Statische Drucker konfiguriert
|
||||
2025-06-20 12:07:25 - [app] app - [INFO] INFO - [STARTUP] Starte Queue Manager...
|
||||
2025-06-20 12:07:25 - [app] app - [INFO] INFO - [STARTUP] ✅ Queue Manager gestartet
|
||||
2025-06-20 12:07:25 - [app] app - [INFO] INFO - [STARTUP] Starte Job Scheduler...
|
||||
2025-06-20 12:07:25 - [app] app - [INFO] INFO - [STARTUP] ✅ Job Scheduler gestartet
|
||||
2025-06-20 12:07:25 - [app] app - [INFO] INFO - [STARTUP] Initialisiere Steckdosen (alle auf 'aus' = frei)...
|
||||
2025-06-20 12:07:43 - [app] app - [WARNING] WARNING - [STARTUP] ⚠️ Keine der 6 Steckdosen konnte initialisiert werden
|
||||
2025-06-20 12:07:43 - [app] app - [INFO] INFO - [STARTUP] 🌐 Server startet auf http://:
|
||||
|
@ -508,3 +508,5 @@
|
||||
2025-06-20 12:05:13 - [core_system] core_system - [INFO] INFO - 📊 Massive Konsolidierung: 6 Dateien → 1 Datei (88% Reduktion)
|
||||
2025-06-20 12:06:21 - [core_system] core_system - [INFO] INFO - ✅ Core System Management Module erfolgreich initialisiert
|
||||
2025-06-20 12:06:21 - [core_system] core_system - [INFO] INFO - 📊 Massive Konsolidierung: 6 Dateien → 1 Datei (88% Reduktion)
|
||||
2025-06-20 12:07:23 - [core_system] core_system - [INFO] INFO - ✅ Core System Management Module erfolgreich initialisiert
|
||||
2025-06-20 12:07:23 - [core_system] core_system - [INFO] INFO - 📊 Massive Konsolidierung: 6 Dateien → 1 Datei (88% Reduktion)
|
||||
|
@ -1047,3 +1047,5 @@
|
||||
2025-06-20 12:05:13 - [data_management] data_management - [INFO] INFO - 📊 Massive Konsolidierung: 3 Dateien → 1 Datei (67% Reduktion)
|
||||
2025-06-20 12:06:21 - [data_management] data_management - [INFO] INFO - ✅ Data Management Module initialisiert
|
||||
2025-06-20 12:06:21 - [data_management] data_management - [INFO] INFO - 📊 Massive Konsolidierung: 3 Dateien → 1 Datei (67% Reduktion)
|
||||
2025-06-20 12:07:24 - [data_management] data_management - [INFO] INFO - ✅ Data Management Module initialisiert
|
||||
2025-06-20 12:07:24 - [data_management] data_management - [INFO] INFO - 📊 Massive Konsolidierung: 3 Dateien → 1 Datei (67% Reduktion)
|
||||
|
@ -111,3 +111,4 @@
|
||||
2025-06-20 12:02:32 - [drucker_steuerung] drucker_steuerung - [INFO] INFO - 🖨️ Drucker-Steuerungs-Blueprint (Backend-Kontrolle) geladen
|
||||
2025-06-20 12:05:14 - [drucker_steuerung] drucker_steuerung - [INFO] INFO - 🖨️ Drucker-Steuerungs-Blueprint (Backend-Kontrolle) geladen
|
||||
2025-06-20 12:06:22 - [drucker_steuerung] drucker_steuerung - [INFO] INFO - 🖨️ Drucker-Steuerungs-Blueprint (Backend-Kontrolle) geladen
|
||||
2025-06-20 12:07:25 - [drucker_steuerung] drucker_steuerung - [INFO] INFO - 🖨️ Drucker-Steuerungs-Blueprint (Backend-Kontrolle) geladen
|
||||
|
@ -840,3 +840,4 @@
|
||||
2025-06-20 12:02:32 - [energy_monitoring] energy_monitoring - [INFO] INFO - ✅ Energiemonitoring-Blueprint initialisiert
|
||||
2025-06-20 12:05:14 - [energy_monitoring] energy_monitoring - [INFO] INFO - ✅ Energiemonitoring-Blueprint initialisiert
|
||||
2025-06-20 12:06:22 - [energy_monitoring] energy_monitoring - [INFO] INFO - ✅ Energiemonitoring-Blueprint initialisiert
|
||||
2025-06-20 12:07:25 - [energy_monitoring] energy_monitoring - [INFO] INFO - ✅ Energiemonitoring-Blueprint initialisiert
|
||||
|
@ -3911,3 +3911,35 @@
|
||||
2025-06-20 12:06:19 - [hardware_integration] hardware_integration - [WARNING] WARNING - ⚠️ Energiedaten von 192.168.0.103 nicht abrufbar: HTTPConnectionPool(host='192.168.0.103', port=80): Max retries exceeded with url: /app (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x00000140D752EAD0>, 'Connection to 192.168.0.103 timed out. (connect timeout=2)'))
|
||||
2025-06-20 12:06:21 - [hardware_integration] hardware_integration - [INFO] INFO - 🚀 Hardware Integration (Backend-Kontrolle) erfolgreich geladen
|
||||
2025-06-20 12:06:23 - [hardware_integration] hardware_integration - [INFO] INFO - 🎯 DruckerSteuerung initialisiert - BACKEND ÜBERNIMMT KONTROLLE
|
||||
2025-06-20 12:06:47 - [hardware_integration] hardware_integration - [WARNING] WARNING - ⚠️ 192.168.0.100 ist über keine Methode erreichbar
|
||||
2025-06-20 12:06:47 - [hardware_integration] hardware_integration - [WARNING] WARNING - ⚠️ 192.168.0.100 ist über keine Methode erreichbar
|
||||
2025-06-20 12:06:47 - [hardware_integration] hardware_integration - [WARNING] WARNING - ⚠️ Steckdose 192.168.0.100 ist im Netzwerk nicht erreichbar
|
||||
2025-06-20 12:06:47 - [hardware_integration] hardware_integration - [WARNING] WARNING - ⚠️ Steckdose 192.168.0.100 ist im Netzwerk nicht erreichbar
|
||||
2025-06-20 12:06:49 - [hardware_integration] hardware_integration - [WARNING] WARNING - ⚠️ Energiedaten von 192.168.0.100 nicht abrufbar: HTTPConnectionPool(host='192.168.0.100', port=80): Max retries exceeded with url: /app (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x000001B1B9A47E00>, 'Connection to 192.168.0.100 timed out. (connect timeout=2)'))
|
||||
2025-06-20 12:06:49 - [hardware_integration] hardware_integration - [WARNING] WARNING - ⚠️ Energiedaten von 192.168.0.100 nicht abrufbar: HTTPConnectionPool(host='192.168.0.100', port=80): Max retries exceeded with url: /app (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x000001B1B9AE7110>, 'Connection to 192.168.0.100 timed out. (connect timeout=2)'))
|
||||
2025-06-20 12:06:51 - [hardware_integration] hardware_integration - [WARNING] WARNING - ⚠️ Energiedaten von 192.168.0.100 nicht abrufbar: HTTPConnectionPool(host='192.168.0.100', port=80): Max retries exceeded with url: /app (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x000001B1B9AE7C50>, 'Connection to 192.168.0.100 timed out. (connect timeout=2)'))
|
||||
2025-06-20 12:06:51 - [hardware_integration] hardware_integration - [WARNING] WARNING - ⚠️ Energiedaten von 192.168.0.100 nicht abrufbar: HTTPConnectionPool(host='192.168.0.100', port=80): Max retries exceeded with url: /app (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x000001B1B9B00D60>, 'Connection to 192.168.0.100 timed out. (connect timeout=2)'))
|
||||
2025-06-20 12:06:53 - [hardware_integration] hardware_integration - [WARNING] WARNING - ⚠️ Energiedaten von 192.168.0.100 nicht abrufbar: HTTPConnectionPool(host='192.168.0.100', port=80): Max retries exceeded with url: /app (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x000001B1B9B016E0>, 'Connection to 192.168.0.100 timed out. (connect timeout=2)'))
|
||||
2025-06-20 12:06:53 - [hardware_integration] hardware_integration - [WARNING] WARNING - ⚠️ Energiedaten von 192.168.0.100 nicht abrufbar: HTTPConnectionPool(host='192.168.0.100', port=80): Max retries exceeded with url: /app (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x000001B1B9A8C950>, 'Connection to 192.168.0.100 timed out. (connect timeout=2)'))
|
||||
2025-06-20 12:06:59 - [hardware_integration] hardware_integration - [WARNING] WARNING - ⚠️ 192.168.0.101 ist über keine Methode erreichbar
|
||||
2025-06-20 12:06:59 - [hardware_integration] hardware_integration - [WARNING] WARNING - ⚠️ Steckdose 192.168.0.101 ist im Netzwerk nicht erreichbar
|
||||
2025-06-20 12:06:59 - [hardware_integration] hardware_integration - [WARNING] WARNING - ⚠️ 192.168.0.101 ist über keine Methode erreichbar
|
||||
2025-06-20 12:06:59 - [hardware_integration] hardware_integration - [WARNING] WARNING - ⚠️ Steckdose 192.168.0.101 ist im Netzwerk nicht erreichbar
|
||||
2025-06-20 12:07:01 - [hardware_integration] hardware_integration - [WARNING] WARNING - ⚠️ Energiedaten von 192.168.0.101 nicht abrufbar: HTTPConnectionPool(host='192.168.0.101', port=80): Max retries exceeded with url: /app (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x000001B1B99CE360>, 'Connection to 192.168.0.101 timed out. (connect timeout=2)'))
|
||||
2025-06-20 12:07:01 - [hardware_integration] hardware_integration - [WARNING] WARNING - ⚠️ Energiedaten von 192.168.0.101 nicht abrufbar: HTTPConnectionPool(host='192.168.0.101', port=80): Max retries exceeded with url: /app (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x000001B1B9BA05A0>, 'Connection to 192.168.0.101 timed out. (connect timeout=2)'))
|
||||
2025-06-20 12:07:03 - [hardware_integration] hardware_integration - [WARNING] WARNING - ⚠️ Energiedaten von 192.168.0.101 nicht abrufbar: HTTPConnectionPool(host='192.168.0.101', port=80): Max retries exceeded with url: /app (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x000001B1B9BA09E0>, 'Connection to 192.168.0.101 timed out. (connect timeout=2)'))
|
||||
2025-06-20 12:07:03 - [hardware_integration] hardware_integration - [WARNING] WARNING - ⚠️ Energiedaten von 192.168.0.101 nicht abrufbar: HTTPConnectionPool(host='192.168.0.101', port=80): Max retries exceeded with url: /app (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x000001B1B9BA0E20>, 'Connection to 192.168.0.101 timed out. (connect timeout=2)'))
|
||||
2025-06-20 12:07:05 - [hardware_integration] hardware_integration - [WARNING] WARNING - ⚠️ Energiedaten von 192.168.0.101 nicht abrufbar: HTTPConnectionPool(host='192.168.0.101', port=80): Max retries exceeded with url: /app (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x000001B1B9BA1260>, 'Connection to 192.168.0.101 timed out. (connect timeout=2)'))
|
||||
2025-06-20 12:07:05 - [hardware_integration] hardware_integration - [WARNING] WARNING - ⚠️ Energiedaten von 192.168.0.101 nicht abrufbar: HTTPConnectionPool(host='192.168.0.101', port=80): Max retries exceeded with url: /app (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x000001B1B9BA16A0>, 'Connection to 192.168.0.101 timed out. (connect timeout=2)'))
|
||||
2025-06-20 12:07:11 - [hardware_integration] hardware_integration - [WARNING] WARNING - ⚠️ 192.168.0.102 ist über keine Methode erreichbar
|
||||
2025-06-20 12:07:11 - [hardware_integration] hardware_integration - [WARNING] WARNING - ⚠️ Steckdose 192.168.0.102 ist im Netzwerk nicht erreichbar
|
||||
2025-06-20 12:07:11 - [hardware_integration] hardware_integration - [WARNING] WARNING - ⚠️ 192.168.0.102 ist über keine Methode erreichbar
|
||||
2025-06-20 12:07:11 - [hardware_integration] hardware_integration - [WARNING] WARNING - ⚠️ Steckdose 192.168.0.102 ist im Netzwerk nicht erreichbar
|
||||
2025-06-20 12:07:13 - [hardware_integration] hardware_integration - [WARNING] WARNING - ⚠️ Energiedaten von 192.168.0.102 nicht abrufbar: HTTPConnectionPool(host='192.168.0.102', port=80): Max retries exceeded with url: /app (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x000001B1B9BA2690>, 'Connection to 192.168.0.102 timed out. (connect timeout=2)'))
|
||||
2025-06-20 12:07:13 - [hardware_integration] hardware_integration - [WARNING] WARNING - ⚠️ Energiedaten von 192.168.0.102 nicht abrufbar: HTTPConnectionPool(host='192.168.0.102', port=80): Max retries exceeded with url: /app (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x000001B1B9BA2030>, 'Connection to 192.168.0.102 timed out. (connect timeout=2)'))
|
||||
2025-06-20 12:07:15 - [hardware_integration] hardware_integration - [WARNING] WARNING - ⚠️ Energiedaten von 192.168.0.102 nicht abrufbar: HTTPConnectionPool(host='192.168.0.102', port=80): Max retries exceeded with url: /app (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x000001B1B9BA28B0>, 'Connection to 192.168.0.102 timed out. (connect timeout=2)'))
|
||||
2025-06-20 12:07:15 - [hardware_integration] hardware_integration - [WARNING] WARNING - ⚠️ Energiedaten von 192.168.0.102 nicht abrufbar: HTTPConnectionPool(host='192.168.0.102', port=80): Max retries exceeded with url: /app (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x000001B1B9BA2CF0>, 'Connection to 192.168.0.102 timed out. (connect timeout=2)'))
|
||||
2025-06-20 12:07:17 - [hardware_integration] hardware_integration - [WARNING] WARNING - ⚠️ Energiedaten von 192.168.0.102 nicht abrufbar: HTTPConnectionPool(host='192.168.0.102', port=80): Max retries exceeded with url: /app (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x000001B1B99CFF00>, 'Connection to 192.168.0.102 timed out. (connect timeout=2)'))
|
||||
2025-06-20 12:07:17 - [hardware_integration] hardware_integration - [WARNING] WARNING - ⚠️ Energiedaten von 192.168.0.102 nicht abrufbar: HTTPConnectionPool(host='192.168.0.102', port=80): Max retries exceeded with url: /app (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x000001B1B99CEBE0>, 'Connection to 192.168.0.102 timed out. (connect timeout=2)'))
|
||||
2025-06-20 12:07:24 - [hardware_integration] hardware_integration - [INFO] INFO - 🚀 Hardware Integration (Backend-Kontrolle) erfolgreich geladen
|
||||
2025-06-20 12:07:25 - [hardware_integration] hardware_integration - [INFO] INFO - 🎯 DruckerSteuerung initialisiert - BACKEND ÜBERNIMMT KONTROLLE
|
||||
|
@ -2032,3 +2032,8 @@
|
||||
2025-06-20 12:06:41 - [job_queue_system] job_queue_system - [ERROR] ERROR - Fehler bei Konflikt-Erkennung: 'Job' object has no attribute 'priority'
|
||||
2025-06-20 12:06:41 - [job_queue_system] job_queue_system - [ERROR] ERROR - Fehler bei Konflikt-Erkennung: 'Job' object has no attribute 'priority'
|
||||
2025-06-20 12:06:41 - [job_queue_system] job_queue_system - [ERROR] ERROR - Fehler bei Konflikt-Erkennung: 'Job' object has no attribute 'priority'
|
||||
2025-06-20 12:07:07 - [job_queue_system] job_queue_system - [ERROR] ERROR - Fehler bei Konflikt-Erkennung: 'Job' object has no attribute 'priority'
|
||||
2025-06-20 12:07:22 - [job_queue_system] job_queue_system - [INFO] INFO - Queue Manager gestoppt (Legacy-Kompatibilität)
|
||||
2025-06-20 12:07:24 - [job_queue_system] job_queue_system - [INFO] INFO - ✅ Job & Queue System Module initialisiert
|
||||
2025-06-20 12:07:24 - [job_queue_system] job_queue_system - [INFO] INFO - 📊 MASSIVE Konsolidierung: 4 Dateien → 1 Datei (75% Reduktion)
|
||||
2025-06-20 12:07:25 - [job_queue_system] job_queue_system - [INFO] INFO - Queue Manager gestartet (Legacy-Kompatibilität)
|
||||
|
@ -1111,3 +1111,13 @@ sqlalchemy.exc.IntegrityError: (sqlite3.IntegrityError) FOREIGN KEY constraint f
|
||||
2025-06-20 12:06:41 - [jobs] jobs - [WARNING] WARNING - ⚠️ Kritische Konflikte gefunden: ["Fehler bei Konflikt-Analyse: 'Job' object has no attribute 'priority'"]
|
||||
2025-06-20 12:06:41 - [jobs] jobs - [WARNING] WARNING - ⚠️ Kritische Konflikte gefunden: ["Fehler bei Konflikt-Analyse: 'Job' object has no attribute 'priority'"]
|
||||
2025-06-20 12:06:41 - [jobs] jobs - [WARNING] WARNING - ⚠️ Kritische Konflikte gefunden: ["Fehler bei Konflikt-Analyse: 'Job' object has no attribute 'priority'"]
|
||||
2025-06-20 12:06:44 - [jobs] jobs - [INFO] INFO - 📋 Jobs-Abfrage gestartet von Benutzer 1 (Admin: True)
|
||||
2025-06-20 12:06:44 - [jobs] jobs - [INFO] INFO - ✅ Jobs erfolgreich abgerufen: 3 von 3 (Seite 1)
|
||||
2025-06-20 12:07:07 - [jobs] jobs - [INFO] INFO - 🚀 Neue Job-Erstellung gestartet von Benutzer 1
|
||||
2025-06-20 12:07:07 - [jobs] jobs - [WARNING] WARNING - ⚠️ Kritische Konflikte gefunden: ["Fehler bei Konflikt-Analyse: 'Job' object has no attribute 'priority'"]
|
||||
2025-06-20 12:07:14 - [jobs] jobs - [INFO] INFO - 📋 Jobs-Abfrage gestartet von Benutzer 1 (Admin: True)
|
||||
2025-06-20 12:07:14 - [jobs] jobs - [INFO] INFO - ✅ Jobs erfolgreich abgerufen: 3 von 3 (Seite 1)
|
||||
2025-06-20 12:07:44 - [jobs] jobs - [INFO] INFO - 📋 Jobs-Abfrage gestartet von Benutzer 1 (Admin: True)
|
||||
2025-06-20 12:07:44 - [jobs] jobs - [INFO] INFO - ✅ Jobs erfolgreich abgerufen: 3 von 3 (Seite 1)
|
||||
2025-06-20 12:08:14 - [jobs] jobs - [INFO] INFO - 📋 Jobs-Abfrage gestartet von Benutzer 1 (Admin: True)
|
||||
2025-06-20 12:08:14 - [jobs] jobs - [INFO] INFO - ✅ Jobs erfolgreich abgerufen: 3 von 3 (Seite 1)
|
||||
|
@ -1035,3 +1035,5 @@
|
||||
2025-06-20 12:05:14 - [monitoring_analytics] monitoring_analytics - [INFO] INFO - 📊 MASSIVE Konsolidierung: 3 Dateien → 1 Datei (67% Reduktion)
|
||||
2025-06-20 12:06:22 - [monitoring_analytics] monitoring_analytics - [INFO] INFO - ✅ Monitoring & Analytics Module initialisiert
|
||||
2025-06-20 12:06:22 - [monitoring_analytics] monitoring_analytics - [INFO] INFO - 📊 MASSIVE Konsolidierung: 3 Dateien → 1 Datei (67% Reduktion)
|
||||
2025-06-20 12:07:25 - [monitoring_analytics] monitoring_analytics - [INFO] INFO - ✅ Monitoring & Analytics Module initialisiert
|
||||
2025-06-20 12:07:25 - [monitoring_analytics] monitoring_analytics - [INFO] INFO - 📊 MASSIVE Konsolidierung: 3 Dateien → 1 Datei (67% Reduktion)
|
||||
|
@ -572,3 +572,4 @@ WHERE users.role = ?]
|
||||
2025-06-20 12:03:09 - [permissions] permissions - [INFO] INFO - UserPermission für Admin-Benutzer 1 aktualisiert
|
||||
2025-06-20 12:05:14 - [permissions] permissions - [INFO] INFO - Admin-Berechtigungen korrigiert: 0 erstellt, 0 aktualisiert
|
||||
2025-06-20 12:06:22 - [permissions] permissions - [INFO] INFO - Admin-Berechtigungen korrigiert: 0 erstellt, 0 aktualisiert
|
||||
2025-06-20 12:07:25 - [permissions] permissions - [INFO] INFO - Admin-Berechtigungen korrigiert: 0 erstellt, 0 aktualisiert
|
||||
|
@ -4720,3 +4720,52 @@
|
||||
2025-06-20 12:06:41 - [scheduler] scheduler - [INFO] INFO - ❌ Fehlgeschlagen: 0
|
||||
2025-06-20 12:06:41 - [scheduler] scheduler - [WARNING] WARNING - ⚠️ KEINE Steckdose konnte initialisiert werden!
|
||||
2025-06-20 12:06:41 - [scheduler] scheduler - [INFO] INFO - ============================================================
|
||||
2025-06-20 12:06:49 - [scheduler] scheduler - [INFO] INFO - 🚀 Starte geplanten Job 1: Gastauftrag: Till Tomczaktet
|
||||
2025-06-20 12:06:49 - [scheduler] scheduler - [ERROR] ERROR - ❌ Fehler beim einschalten der Steckdose für Drucker 2: name 'tapo_controller' is not defined
|
||||
2025-06-20 12:06:49 - [scheduler] scheduler - [ERROR] ERROR - ❌ Konnte Steckdose für Job 1 nicht einschalten
|
||||
2025-06-20 12:06:53 - [scheduler] scheduler - [INFO] INFO - 🚀 Starte geplanten Job 1: Gastauftrag: Till Tomczaktet
|
||||
2025-06-20 12:06:53 - [scheduler] scheduler - [ERROR] ERROR - ❌ Fehler beim einschalten der Steckdose für Drucker 2: name 'tapo_controller' is not defined
|
||||
2025-06-20 12:06:53 - [scheduler] scheduler - [ERROR] ERROR - ❌ Konnte Steckdose für Job 1 nicht einschalten
|
||||
2025-06-20 12:07:19 - [scheduler] scheduler - [INFO] INFO - 🚀 Starte geplanten Job 1: Gastauftrag: Till Tomczaktet
|
||||
2025-06-20 12:07:19 - [scheduler] scheduler - [ERROR] ERROR - ❌ Fehler beim einschalten der Steckdose für Drucker 2: name 'tapo_controller' is not defined
|
||||
2025-06-20 12:07:19 - [scheduler] scheduler - [ERROR] ERROR - ❌ Konnte Steckdose für Job 1 nicht einschalten
|
||||
2025-06-20 12:07:24 - [scheduler] scheduler - [INFO] INFO - Task check_jobs registriert: Intervall 30s, Enabled: True
|
||||
2025-06-20 12:07:25 - [scheduler] scheduler - [INFO] INFO - Scheduler-Thread gestartet
|
||||
2025-06-20 12:07:25 - [scheduler] scheduler - [INFO] INFO - Scheduler gestartet
|
||||
2025-06-20 12:07:25 - [scheduler] scheduler - [INFO] INFO - 🚀 Starte Steckdosen-Initialisierung beim Systemstart...
|
||||
2025-06-20 12:07:25 - [scheduler] scheduler - [INFO] INFO - 🔍 Prüfe 6 konfigurierte Steckdosen...
|
||||
2025-06-20 12:07:25 - [scheduler] scheduler - [INFO] INFO - 🚀 Starte geplanten Job 1: Gastauftrag: Till Tomczaktet
|
||||
2025-06-20 12:07:25 - [scheduler] scheduler - [ERROR] ERROR - ❌ Fehler beim einschalten der Steckdose für Drucker 2: name 'tapo_controller' is not defined
|
||||
2025-06-20 12:07:25 - [scheduler] scheduler - [ERROR] ERROR - ❌ Konnte Steckdose für Job 1 nicht einschalten
|
||||
2025-06-20 12:07:28 - [scheduler] scheduler - [WARNING] WARNING - 📡 Drucker 1: Steckdose 192.168.0.100 nicht erreichbar
|
||||
2025-06-20 12:07:31 - [scheduler] scheduler - [WARNING] WARNING - 📡 Drucker 2: Steckdose 192.168.0.101 nicht erreichbar
|
||||
2025-06-20 12:07:34 - [scheduler] scheduler - [WARNING] WARNING - 📡 Drucker 3: Steckdose 192.168.0.102 nicht erreichbar
|
||||
2025-06-20 12:07:37 - [scheduler] scheduler - [WARNING] WARNING - 📡 Drucker 4: Steckdose 192.168.0.103 nicht erreichbar
|
||||
2025-06-20 12:07:40 - [scheduler] scheduler - [WARNING] WARNING - 📡 Drucker 5: Steckdose 192.168.0.104 nicht erreichbar
|
||||
2025-06-20 12:07:43 - [scheduler] scheduler - [WARNING] WARNING - 📡 Drucker 6: Steckdose 192.168.0.106 nicht erreichbar
|
||||
2025-06-20 12:07:43 - [scheduler] scheduler - [INFO] INFO - ============================================================
|
||||
2025-06-20 12:07:43 - [scheduler] scheduler - [INFO] INFO - 🎯 STECKDOSEN-INITIALISIERUNG ABGESCHLOSSEN
|
||||
2025-06-20 12:07:43 - [scheduler] scheduler - [INFO] INFO - 📊 Gesamt: 6 Steckdosen
|
||||
2025-06-20 12:07:43 - [scheduler] scheduler - [INFO] INFO - ✅ Erfolgreich: 0
|
||||
2025-06-20 12:07:43 - [scheduler] scheduler - [INFO] INFO - 📡 Nicht erreichbar: 6
|
||||
2025-06-20 12:07:43 - [scheduler] scheduler - [INFO] INFO - ❌ Fehlgeschlagen: 0
|
||||
2025-06-20 12:07:43 - [scheduler] scheduler - [WARNING] WARNING - ⚠️ KEINE Steckdose konnte initialisiert werden!
|
||||
2025-06-20 12:07:43 - [scheduler] scheduler - [INFO] INFO - ============================================================
|
||||
2025-06-20 12:07:49 - [scheduler] scheduler - [INFO] INFO - 🚀 Starte geplanten Job 1: Gastauftrag: Till Tomczaktet
|
||||
2025-06-20 12:07:49 - [scheduler] scheduler - [ERROR] ERROR - ❌ Fehler beim einschalten der Steckdose für Drucker 2: name 'tapo_controller' is not defined
|
||||
2025-06-20 12:07:49 - [scheduler] scheduler - [ERROR] ERROR - ❌ Konnte Steckdose für Job 1 nicht einschalten
|
||||
2025-06-20 12:07:55 - [scheduler] scheduler - [INFO] INFO - 🚀 Starte geplanten Job 1: Gastauftrag: Till Tomczaktet
|
||||
2025-06-20 12:07:55 - [scheduler] scheduler - [ERROR] ERROR - ❌ Fehler beim einschalten der Steckdose für Drucker 2: name 'tapo_controller' is not defined
|
||||
2025-06-20 12:07:55 - [scheduler] scheduler - [ERROR] ERROR - ❌ Konnte Steckdose für Job 1 nicht einschalten
|
||||
2025-06-20 12:08:19 - [scheduler] scheduler - [INFO] INFO - 🚀 Starte geplanten Job 1: Gastauftrag: Till Tomczaktet
|
||||
2025-06-20 12:08:19 - [scheduler] scheduler - [ERROR] ERROR - ❌ Fehler beim einschalten der Steckdose für Drucker 2: name 'tapo_controller' is not defined
|
||||
2025-06-20 12:08:19 - [scheduler] scheduler - [ERROR] ERROR - ❌ Konnte Steckdose für Job 1 nicht einschalten
|
||||
2025-06-20 12:08:19 - [scheduler] scheduler - [INFO] INFO - 🚀 Starte geplanten Job 2: Gastauftrag: Till Tomczaktet
|
||||
2025-06-20 12:08:19 - [scheduler] scheduler - [ERROR] ERROR - ❌ Fehler beim einschalten der Steckdose für Drucker 2: name 'tapo_controller' is not defined
|
||||
2025-06-20 12:08:19 - [scheduler] scheduler - [ERROR] ERROR - ❌ Konnte Steckdose für Job 2 nicht einschalten
|
||||
2025-06-20 12:08:25 - [scheduler] scheduler - [INFO] INFO - 🚀 Starte geplanten Job 1: Gastauftrag: Till Tomczaktet
|
||||
2025-06-20 12:08:25 - [scheduler] scheduler - [ERROR] ERROR - ❌ Fehler beim einschalten der Steckdose für Drucker 2: name 'tapo_controller' is not defined
|
||||
2025-06-20 12:08:25 - [scheduler] scheduler - [ERROR] ERROR - ❌ Konnte Steckdose für Job 1 nicht einschalten
|
||||
2025-06-20 12:08:25 - [scheduler] scheduler - [INFO] INFO - 🚀 Starte geplanten Job 2: Gastauftrag: Till Tomczaktet
|
||||
2025-06-20 12:08:25 - [scheduler] scheduler - [ERROR] ERROR - ❌ Fehler beim einschalten der Steckdose für Drucker 2: name 'tapo_controller' is not defined
|
||||
2025-06-20 12:08:25 - [scheduler] scheduler - [ERROR] ERROR - ❌ Konnte Steckdose für Job 2 nicht einschalten
|
||||
|
@ -1565,3 +1565,6 @@
|
||||
2025-06-20 12:06:21 - [security_suite] security_suite - [INFO] INFO - ✅ Security Suite Module initialisiert
|
||||
2025-06-20 12:06:21 - [security_suite] security_suite - [INFO] INFO - 📊 Massive Konsolidierung: 3 Dateien → 1 Datei (67% Reduktion)
|
||||
2025-06-20 12:06:22 - [security_suite] security_suite - [INFO] INFO - 🔒 Security Suite initialisiert
|
||||
2025-06-20 12:07:24 - [security_suite] security_suite - [INFO] INFO - ✅ Security Suite Module initialisiert
|
||||
2025-06-20 12:07:24 - [security_suite] security_suite - [INFO] INFO - 📊 Massive Konsolidierung: 3 Dateien → 1 Datei (67% Reduktion)
|
||||
2025-06-20 12:07:25 - [security_suite] security_suite - [INFO] INFO - 🔒 Security Suite initialisiert
|
||||
|
@ -4142,3 +4142,12 @@
|
||||
2025-06-20 12:06:22 - [startup] startup - [INFO] INFO - 🪟 Windows-Modus: Aktiviert
|
||||
2025-06-20 12:06:22 - [startup] startup - [INFO] INFO - 🔒 Windows-sichere Log-Rotation: Aktiviert
|
||||
2025-06-20 12:06:22 - [startup] startup - [INFO] INFO - ==================================================
|
||||
2025-06-20 12:07:25 - [startup] startup - [INFO] INFO - ==================================================
|
||||
2025-06-20 12:07:25 - [startup] startup - [INFO] INFO - [START] MYP Platform Backend wird gestartet...
|
||||
2025-06-20 12:07:25 - [startup] startup - [INFO] INFO - 🐍 Python Version: 3.13.3 (tags/v3.13.3:6280bb5, Apr 8 2025, 14:47:33) [MSC v.1943 64 bit (AMD64)]
|
||||
2025-06-20 12:07:25 - [startup] startup - [INFO] INFO - 💻 Betriebssystem: nt (win32)
|
||||
2025-06-20 12:07:25 - [startup] startup - [INFO] INFO - 📁 Arbeitsverzeichnis: C:\Users\TTOMCZA.EMEA\Dev\Projektarbeit-MYP\backend
|
||||
2025-06-20 12:07:25 - [startup] startup - [INFO] INFO - ⏰ Startzeit: 2025-06-20T12:07:25.305331
|
||||
2025-06-20 12:07:25 - [startup] startup - [INFO] INFO - 🪟 Windows-Modus: Aktiviert
|
||||
2025-06-20 12:07:25 - [startup] startup - [INFO] INFO - 🔒 Windows-sichere Log-Rotation: Aktiviert
|
||||
2025-06-20 12:07:25 - [startup] startup - [INFO] INFO - ==================================================
|
||||
|
@ -1365,3 +1365,7 @@
|
||||
2025-06-20 12:05:13 - [utilities_collection] utilities_collection - [INFO] INFO - 🚨 ALLERLETZTE MEGA-Konsolidierung: 12+ Dateien → 1 Datei (90%+ Reduktion)
|
||||
2025-06-20 12:05:52 - [utilities_collection] utilities_collection - [INFO] INFO - ✅ Utilities Collection initialisiert
|
||||
2025-06-20 12:05:52 - [utilities_collection] utilities_collection - [INFO] INFO - 🚨 ALLERLETZTE MEGA-Konsolidierung: 12+ Dateien → 1 Datei (90%+ Reduktion)
|
||||
2025-06-20 12:06:21 - [utilities_collection] utilities_collection - [INFO] INFO - ✅ Utilities Collection initialisiert
|
||||
2025-06-20 12:06:21 - [utilities_collection] utilities_collection - [INFO] INFO - 🚨 ALLERLETZTE MEGA-Konsolidierung: 12+ Dateien → 1 Datei (90%+ Reduktion)
|
||||
2025-06-20 12:07:24 - [utilities_collection] utilities_collection - [INFO] INFO - ✅ Utilities Collection initialisiert
|
||||
2025-06-20 12:07:24 - [utilities_collection] utilities_collection - [INFO] INFO - 🚨 ALLERLETZTE MEGA-Konsolidierung: 12+ Dateien → 1 Datei (90%+ Reduktion)
|
||||
|
@ -511,3 +511,5 @@
|
||||
2025-06-20 12:05:13 - [windows_fixes] windows_fixes - [INFO] INFO - ✅ Alle Windows-Fixes erfolgreich angewendet
|
||||
2025-06-20 12:06:21 - [windows_fixes] windows_fixes - [INFO] INFO - 🔧 Wende Windows-spezifische Fixes an...
|
||||
2025-06-20 12:06:21 - [windows_fixes] windows_fixes - [INFO] INFO - ✅ Alle Windows-Fixes erfolgreich angewendet
|
||||
2025-06-20 12:07:23 - [windows_fixes] windows_fixes - [INFO] INFO - 🔧 Wende Windows-spezifische Fixes an...
|
||||
2025-06-20 12:07:23 - [windows_fixes] windows_fixes - [INFO] INFO - ✅ Alle Windows-Fixes erfolgreich angewendet
|
||||
|
1
backend/static/js/charts/chart.min.js
vendored
1
backend/static/js/charts/chart.min.js
vendored
File diff suppressed because one or more lines are too long
@ -281,17 +281,38 @@ window.refreshJobs = async function() {
|
||||
return '';
|
||||
}
|
||||
|
||||
// Verbesserte Feldermapping für Frontend-Kompatibilität
|
||||
const jobName = job.name || job.title || job.filename || job.file_name || 'Unbekannter Job';
|
||||
const printerName = job.printer_name || (job.printer?.name) || 'Unbekannter Drucker';
|
||||
const userName = job.user_name || (job.user?.name) || 'Unbekannter Benutzer';
|
||||
const statusText = job.status_text || job.status || 'Unbekannt';
|
||||
const createdDate = job.created_time || (job.created_at ? new Date(job.created_at).toLocaleDateString('de-DE') : 'Unbekannt');
|
||||
const progress = job.progress || 0;
|
||||
|
||||
return `
|
||||
<div class="job-card p-4 border rounded-lg bg-white dark:bg-slate-800 shadow-sm hover:shadow-md transition-shadow">
|
||||
<h3 class="font-semibold text-gray-900 dark:text-white mb-2">
|
||||
${job.filename || job.title || job.name || 'Unbekannter Job'}
|
||||
</h3>
|
||||
<div class="flex justify-between items-start mb-3">
|
||||
<h3 class="font-semibold text-gray-900 dark:text-white text-lg">
|
||||
${jobName}
|
||||
</h3>
|
||||
<span class="inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium ${getStatusBadgeClass(job.status)}">
|
||||
${statusText}
|
||||
</span>
|
||||
</div>
|
||||
<div class="text-sm text-gray-600 dark:text-gray-400 space-y-1">
|
||||
<p><span class="font-medium">ID:</span> ${job.id || 'N/A'}</p>
|
||||
<p><span class="font-medium">Status:</span> ${job.status || 'Unbekannt'}</p>
|
||||
${job.printer_name ? `<p><span class="font-medium">Drucker:</span> ${job.printer_name}</p>` : ''}
|
||||
${job.created_at ? `<p><span class="font-medium">Erstellt:</span> ${new Date(job.created_at).toLocaleDateString('de-DE')}</p>` : ''}
|
||||
<p><span class="font-medium">Drucker:</span> ${printerName}</p>
|
||||
<p><span class="font-medium">Benutzer:</span> ${userName}</p>
|
||||
<p><span class="font-medium">Erstellt:</span> ${createdDate}</p>
|
||||
${progress > 0 ? `<p><span class="font-medium">Fortschritt:</span> ${progress}%</p>` : ''}
|
||||
</div>
|
||||
${progress > 0 ? `
|
||||
<div class="mt-3">
|
||||
<div class="w-full bg-gray-200 rounded-full h-2">
|
||||
<div class="bg-blue-600 h-2 rounded-full" style="width: ${progress}%"></div>
|
||||
</div>
|
||||
</div>
|
||||
` : ''}
|
||||
</div>
|
||||
`;
|
||||
}).filter(card => card !== '').join('');
|
||||
@ -342,13 +363,12 @@ window.refreshJobs = async function() {
|
||||
<div class="text-red-400 dark:text-red-600 text-6xl mb-4">⚠️</div>
|
||||
<h3 class="text-lg font-medium text-gray-900 dark:text-white mb-2">Fehler beim Laden</h3>
|
||||
<p class="text-gray-500 dark:text-gray-400 mb-4">${errorMessage}</p>
|
||||
<button onclick="refreshJobs()" class="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700 transition-colors">
|
||||
<button onclick="refreshJobs()" class="px-4 py-2 bg-blue-600 text-white rounded-lg hover:bg-blue-700">
|
||||
Erneut versuchen
|
||||
</button>
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
} finally {
|
||||
if (refreshButton) {
|
||||
refreshButton.disabled = false;
|
||||
@ -733,4 +753,24 @@ document.addEventListener('visibilitychange', function() {
|
||||
}
|
||||
});
|
||||
|
||||
console.log('🔄 Globale Refresh-Funktionen geladen');
|
||||
console.log('🔄 Globale Refresh-Funktionen geladen');
|
||||
|
||||
/**
|
||||
* Hilfsfunktion für Status-Badge-CSS-Klassen
|
||||
*/
|
||||
function getStatusBadgeClass(status) {
|
||||
const statusClasses = {
|
||||
'scheduled': 'bg-blue-100 text-blue-800 dark:bg-blue-900/20 dark:text-blue-400',
|
||||
'pending': 'bg-yellow-100 text-yellow-800 dark:bg-yellow-900/20 dark:text-yellow-400',
|
||||
'running': 'bg-green-100 text-green-800 dark:bg-green-900/20 dark:text-green-400',
|
||||
'printing': 'bg-green-100 text-green-800 dark:bg-green-900/20 dark:text-green-400',
|
||||
'completed': 'bg-gray-100 text-gray-800 dark:bg-gray-900/20 dark:text-gray-400',
|
||||
'finished': 'bg-gray-100 text-gray-800 dark:bg-gray-900/20 dark:text-gray-400',
|
||||
'failed': 'bg-red-100 text-red-800 dark:bg-red-900/20 dark:text-red-400',
|
||||
'cancelled': 'bg-gray-100 text-gray-800 dark:bg-gray-900/20 dark:text-gray-400',
|
||||
'aborted': 'bg-red-100 text-red-800 dark:bg-red-900/20 dark:text-red-400',
|
||||
'paused': 'bg-orange-100 text-orange-800 dark:bg-orange-900/20 dark:text-orange-400'
|
||||
};
|
||||
|
||||
return statusClasses[status] || 'bg-gray-100 text-gray-800 dark:bg-gray-900/20 dark:text-gray-400';
|
||||
}
|
@ -1059,15 +1059,16 @@ class JobManager {
|
||||
const fileArea = document.getElementById('file-upload-area');
|
||||
const fileInput = document.getElementById('stl_file');
|
||||
|
||||
fileArea.addEventListener('click', () => fileInput.click());
|
||||
fileArea.addEventListener('dragover', this.handleDragOver.bind(this));
|
||||
fileArea.addEventListener('dragleave', this.handleDragLeave.bind(this));
|
||||
fileArea.addEventListener('drop', this.handleFileDrop.bind(this));
|
||||
fileInput.addEventListener('change', this.handleFileSelect.bind(this));
|
||||
if (fileArea && fileInput) {
|
||||
fileArea.addEventListener('click', () => fileInput.click());
|
||||
fileArea.addEventListener('dragover', this.handleDragOver.bind(this));
|
||||
fileArea.addEventListener('dragleave', this.handleDragLeave.bind(this));
|
||||
fileArea.addEventListener('drop', this.handleFileDrop.bind(this));
|
||||
fileInput.addEventListener('change', this.handleFileSelect.bind(this));
|
||||
}
|
||||
|
||||
// Form Submissions
|
||||
document.getElementById('newJobForm').addEventListener('submit', this.handleJobSubmit.bind(this));
|
||||
document.getElementById('quickReservationForm').addEventListener('submit', this.handleQuickReservation.bind(this));
|
||||
// Form Submissions - Robuste Registrierung
|
||||
this.setupFormSubmitListeners();
|
||||
|
||||
// Modal Close Events
|
||||
document.addEventListener('keydown', (e) => {
|
||||
@ -1077,6 +1078,80 @@ class JobManager {
|
||||
});
|
||||
}
|
||||
|
||||
setupFormSubmitListeners() {
|
||||
// Main Job Form Handler - Robust mit Retry-Mechanismus
|
||||
const setupMainFormListener = () => {
|
||||
const mainForm = document.getElementById('newJobForm');
|
||||
if (mainForm) {
|
||||
console.log('✅ Hauptformular gefunden - Event Listener wird registriert');
|
||||
// Entferne vorherige Listener um Duplikate zu vermeiden
|
||||
mainForm.removeEventListener('submit', this.handleJobSubmit.bind(this));
|
||||
mainForm.addEventListener('submit', this.handleJobSubmit.bind(this));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
// Quick Reservation Form Handler
|
||||
const setupQuickFormListener = () => {
|
||||
const quickForm = document.getElementById('quickReservationForm');
|
||||
if (quickForm) {
|
||||
console.log('✅ Schnell-Reservierung Formular gefunden - Event Listener wird registriert');
|
||||
quickForm.removeEventListener('submit', this.handleQuickReservation.bind(this));
|
||||
quickForm.addEventListener('submit', this.handleQuickReservation.bind(this));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
// Sofort versuchen
|
||||
const mainFormReady = setupMainFormListener();
|
||||
const quickFormReady = setupQuickFormListener();
|
||||
|
||||
// Falls Formulare nicht sofort verfügbar sind, mit Observer überwachen
|
||||
if (!mainFormReady || !quickFormReady) {
|
||||
console.log('⏳ Einige Formulare nicht sofort verfügbar - verwende MutationObserver');
|
||||
|
||||
const observer = new MutationObserver(() => {
|
||||
if (!mainFormReady && setupMainFormListener()) {
|
||||
console.log('✅ Hauptformular nachträglich gefunden und registriert');
|
||||
}
|
||||
if (!quickFormReady && setupQuickFormListener()) {
|
||||
console.log('✅ Schnell-Formular nachträglich gefunden und registriert');
|
||||
}
|
||||
});
|
||||
|
||||
observer.observe(document.body, {
|
||||
childList: true,
|
||||
subtree: true
|
||||
});
|
||||
|
||||
// Observer nach 10 Sekunden stoppen
|
||||
setTimeout(() => observer.disconnect(), 10000);
|
||||
}
|
||||
|
||||
// Default-Startzeiten setzen
|
||||
this.setDefaultStartTimes();
|
||||
}
|
||||
|
||||
setDefaultStartTimes() {
|
||||
// Startzeit für Quick Reservation
|
||||
const startTimeInput = document.getElementById('quick-start-time');
|
||||
if (startTimeInput) {
|
||||
const now = new Date();
|
||||
now.setMinutes(now.getMinutes() - now.getTimezoneOffset());
|
||||
startTimeInput.value = now.toISOString().slice(0, 16);
|
||||
}
|
||||
|
||||
// Startzeit für Hauptformular
|
||||
const mainStartTimeInput = document.getElementById('start_time');
|
||||
if (mainStartTimeInput) {
|
||||
const now = new Date();
|
||||
now.setMinutes(now.getMinutes() - now.getTimezoneOffset());
|
||||
mainStartTimeInput.value = now.toISOString().slice(0, 16);
|
||||
}
|
||||
}
|
||||
|
||||
async loadJobs() {
|
||||
try {
|
||||
document.getElementById('jobs-loading').classList.remove('hidden');
|
||||
@ -1893,6 +1968,10 @@ class JobManager {
|
||||
async handleJobSubmit(e) {
|
||||
e.preventDefault();
|
||||
|
||||
console.log('🚀 Job-Submit gestartet');
|
||||
console.log('📋 Event:', e);
|
||||
console.log('📋 Form:', e.target);
|
||||
|
||||
const formData = new FormData(e.target);
|
||||
const jobData = {
|
||||
printer_id: parseInt(formData.get('printer_id')),
|
||||
@ -1901,23 +1980,54 @@ class JobManager {
|
||||
name: formData.get('job_title') || 'Neuer Druckjob'
|
||||
};
|
||||
|
||||
console.log('📋 Job-Daten:', jobData);
|
||||
|
||||
// Validierung
|
||||
if (!jobData.printer_id) {
|
||||
this.showError('Bitte wählen Sie einen Drucker aus');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!jobData.start_iso) {
|
||||
this.showError('Bitte geben Sie eine Startzeit an');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!jobData.duration_minutes || jobData.duration_minutes <= 0) {
|
||||
this.showError('Bitte geben Sie eine gültige Dauer ein');
|
||||
return;
|
||||
}
|
||||
|
||||
if (!jobData.name || jobData.name.trim() === '') {
|
||||
this.showError('Bitte geben Sie einen Job-Titel ein');
|
||||
return;
|
||||
}
|
||||
|
||||
// Submit-Button deaktivieren um Doppel-Submits zu verhindern
|
||||
const submitBtn = e.target.querySelector('button[type="submit"]');
|
||||
if (submitBtn) {
|
||||
submitBtn.disabled = true;
|
||||
submitBtn.innerHTML = '<span class="loading-spinner"></span> Erstelle...';
|
||||
}
|
||||
|
||||
// File upload handling (optional)
|
||||
const fileInput = document.getElementById('stl_file');
|
||||
let uploadedFilePath = null;
|
||||
|
||||
if (fileInput.files.length > 0) {
|
||||
if (fileInput && fileInput.files.length > 0) {
|
||||
try {
|
||||
console.log('📁 Datei-Upload gestartet');
|
||||
// Datei hochladen
|
||||
const uploadResult = await this.uploadJobFile(fileInput.files[0]);
|
||||
if (uploadResult.success) {
|
||||
uploadedFilePath = uploadResult.path;
|
||||
console.log('Datei erfolgreich hochgeladen:', uploadResult.filename);
|
||||
console.log('✅ Datei erfolgreich hochgeladen:', uploadResult.filename);
|
||||
} else {
|
||||
this.showError(`Fehler beim Datei-Upload: ${uploadResult.error}`);
|
||||
return;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Fehler beim Datei-Upload:', error);
|
||||
console.error('❌ Fehler beim Datei-Upload:', error);
|
||||
this.showError('Fehler beim Hochladen der Datei');
|
||||
return;
|
||||
}
|
||||
@ -1929,6 +2039,7 @@ class JobManager {
|
||||
}
|
||||
|
||||
try {
|
||||
console.log('🌐 Sende API-Request');
|
||||
const response = await fetch('/api/jobs', {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
@ -1938,7 +2049,9 @@ class JobManager {
|
||||
body: JSON.stringify(jobData)
|
||||
});
|
||||
|
||||
console.log('📡 API Response Status:', response.status);
|
||||
const data = await response.json();
|
||||
console.log('📡 API Response Data:', data);
|
||||
|
||||
if (data.success) {
|
||||
this.showSuccess('Job erfolgreich erstellt!');
|
||||
@ -1948,13 +2061,34 @@ class JobManager {
|
||||
e.target.reset();
|
||||
|
||||
// Collapse form
|
||||
toggleFormExpansion();
|
||||
const expandedForm = document.getElementById('expanded-form');
|
||||
if (expandedForm && !expandedForm.classList.contains('hidden')) {
|
||||
toggleFormExpansion();
|
||||
}
|
||||
|
||||
// Show additional info if immediate start
|
||||
if (data.immediate_start) {
|
||||
setTimeout(() => {
|
||||
this.showSuccess('Job wurde sofort gestartet und Drucker eingeschaltet!');
|
||||
}, 1000);
|
||||
}
|
||||
} else {
|
||||
this.showError(`Fehler beim Erstellen: ${data.error}`);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error creating job:', error);
|
||||
console.error('❌ Fehler beim Job-Submit:', error);
|
||||
this.showError('Fehler beim Erstellen des Jobs');
|
||||
} finally {
|
||||
// Submit-Button wieder aktivieren
|
||||
if (submitBtn) {
|
||||
submitBtn.disabled = false;
|
||||
submitBtn.innerHTML = `
|
||||
<svg class="w-5 h-5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
||||
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 6v6m0 0v6m0-6h6m-6 0H6"/>
|
||||
</svg>
|
||||
<span>Reservierung erstellen</span>
|
||||
`;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -2156,16 +2290,39 @@ function showQuickReservation() {
|
||||
}
|
||||
|
||||
function toggleFormExpansion() {
|
||||
console.log('🔄 toggleFormExpansion() aufgerufen');
|
||||
const expandedForm = document.getElementById('expanded-form');
|
||||
const toggleBtn = document.getElementById('form-toggle-btn');
|
||||
const toggleText = toggleBtn.querySelector('span');
|
||||
const toggleIcon = toggleBtn.querySelector('svg');
|
||||
|
||||
console.log('📋 Expandierte Form:', expandedForm);
|
||||
console.log('🔘 Toggle-Button:', toggleBtn);
|
||||
|
||||
if (expandedForm.classList.contains('hidden')) {
|
||||
console.log('👁️ Formular wird angezeigt');
|
||||
expandedForm.classList.remove('hidden');
|
||||
toggleText.textContent = 'Reduziert';
|
||||
toggleIcon.style.transform = 'rotate(180deg)';
|
||||
|
||||
// Event-Listener für das Formular erneut registrieren falls nötig
|
||||
setTimeout(() => {
|
||||
const form = document.getElementById('newJobForm');
|
||||
if (form && !form.hasAttribute('data-listener-added')) {
|
||||
console.log('🔧 Registriere Event-Listener für erweiterte Form');
|
||||
form.addEventListener('submit', (e) => {
|
||||
console.log('📨 Formular-Submit über direkten Listener');
|
||||
if (window.jobManager) {
|
||||
window.jobManager.handleJobSubmit(e);
|
||||
} else {
|
||||
console.error('❌ JobManager nicht verfügbar');
|
||||
}
|
||||
});
|
||||
form.setAttribute('data-listener-added', 'true');
|
||||
}
|
||||
}, 100);
|
||||
} else {
|
||||
console.log('👁️🗨️ Formular wird versteckt');
|
||||
expandedForm.classList.add('hidden');
|
||||
toggleText.textContent = 'Erweitert';
|
||||
toggleIcon.style.transform = 'rotate(0deg)';
|
||||
|
Reference in New Issue
Block a user