🐛 Backend Documentation Fix for Button Reservation Creation Issue & Undefined Jobs Problem 🖥️📚
This commit is contained in:
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():
|
||||
|
Reference in New Issue
Block a user