11 KiB
Drag & Drop System für Job-Reihenfolge-Verwaltung
Implementiert am: ${new Date().toLocaleDateString('de-DE')} Status: ✅ Vollständig implementiert und getestet
Überblick
Das Drag & Drop System ermöglicht es Benutzern, die Reihenfolge der Druckjobs per Drag & Drop zu ändern. Die Implementierung umfasst eine vollständige Backend-API, Datenbank-Persistierung und erweiterte Funktionen für Job-Management.
🎯 Hauptfunktionen
✅ Implementierte Features
- Persistent Job-Reihenfolge: Jobs werden in der Datenbank gespeichert und überleben Neustarts
- Benutzerberechtigungen: Nur autorisierte Benutzer können Job-Reihenfolgen ändern
- Automatische Bereinigung: Abgeschlossene Jobs werden automatisch aus der Reihenfolge entfernt
- Cache-System: Optimierte Performance durch intelligentes Caching
- Audit-Trail: Vollständige Nachverfolgung wer wann Änderungen vorgenommen hat
- API-Endpoints: RESTful API für Frontend-Integration
- Drucker-spezifische Reihenfolgen: Jeder Drucker hat seine eigene Job-Reihenfolge
🗄️ Datenbank-Schema
JobOrder-Tabelle
CREATE TABLE job_orders (
id INTEGER PRIMARY KEY,
printer_id INTEGER NOT NULL,
job_id INTEGER NOT NULL,
order_position INTEGER NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
last_modified_by INTEGER,
FOREIGN KEY (printer_id) REFERENCES printers(id),
FOREIGN KEY (job_id) REFERENCES jobs(id),
FOREIGN KEY (last_modified_by) REFERENCES users(id)
);
Eigenschaften
- Eindeutige Job-Position: Jeder Job hat nur eine Position pro Drucker
- Automatische Zeitstempel: created_at und updated_at werden automatisch verwaltet
- Benutzer-Nachverfolgung: last_modified_by speichert wer die Änderung vorgenommen hat
- Referentielle Integrität: Foreign Keys gewährleisten Datenkonsistenz
🔧 Backend-Implementierung
DragDropManager-Klasse
# utils/drag_drop_system.py
class DragDropManager:
def __init__(self):
self.upload_sessions = {}
self.job_order_cache = {} # Cache für bessere Performance
def update_job_order(self, printer_id: int, job_ids: List[int]) -> bool:
"""Aktualisiert die Job-Reihenfolge mit vollständiger Validierung"""
def get_ordered_jobs_for_printer(self, printer_id: int) -> List[Job]:
"""Holt Jobs in der korrekten benutzerdefinierten Reihenfolge"""
def remove_job_from_order(self, job_id: int) -> bool:
"""Entfernt einen Job aus allen Reihenfolgen"""
def cleanup_invalid_orders(self):
"""Bereinigt ungültige oder abgeschlossene Jobs"""
JobOrder-Model
# models.py
class JobOrder(Base):
"""Speichert die benutzerdefinierte Job-Reihenfolge pro Drucker"""
@classmethod
def update_printer_order(cls, printer_id: int, job_ids: List[int],
modified_by_user_id: int = None) -> bool:
"""Aktualisiert die komplette Job-Reihenfolge für einen Drucker"""
@classmethod
def get_ordered_job_ids(cls, printer_id: int) -> List[int]:
"""Holt die Job-IDs in der korrekten Reihenfolge"""
@classmethod
def cleanup_invalid_orders(cls):
"""Bereinigt ungültige Order-Einträge"""
🌐 API-Endpoints
1. Job-Reihenfolge abrufen
GET /api/printers/{printer_id}/jobs/order
Response:
{
"success": true,
"printer": {
"id": 1,
"name": "Drucker A1",
"model": "Prusa i3 MK3S+",
"location": "Raum A.123"
},
"jobs": [
{
"id": 15,
"name": "Smartphone-Hülle",
"user_name": "Max Mustermann",
"duration_minutes": 45,
"status": "scheduled"
}
],
"job_order": [15, 23, 7],
"total_jobs": 3,
"total_duration_minutes": 120
}
2. Job-Reihenfolge aktualisieren
POST /api/printers/{printer_id}/jobs/order
Content-Type: application/json
{
"job_ids": [23, 15, 7] // Neue Reihenfolge
}
Response:
{
"success": true,
"message": "Job-Reihenfolge erfolgreich aktualisiert",
"printer": {
"id": 1,
"name": "Drucker A1"
},
"old_order": [23, 15, 7],
"new_order": [23, 15, 7],
"total_jobs": 3,
"updated_by": {
"id": 5,
"name": "Max Mustermann"
},
"timestamp": "2025-01-13T10:30:00Z"
}
3. Drucker-Job-Zusammenfassung
GET /api/printers/{printer_id}/jobs/summary
Response:
{
"success": true,
"printer": {
"id": 1,
"name": "Drucker A1",
"status": "idle"
},
"summary": {
"printer_id": 1,
"total_jobs": 3,
"total_duration_minutes": 120,
"estimated_completion": "2025-01-13T12:30:00Z",
"next_job": {
"id": 23,
"name": "Ersatzteil XY",
"user": "Anna Schmidt"
},
"jobs": [
{
"position": 0,
"job_id": 23,
"name": "Ersatzteil XY",
"duration_minutes": 30,
"user_name": "Anna Schmidt",
"status": "scheduled"
}
]
}
}
4. Bereinigung ungültiger Reihenfolgen (Admin)
POST /api/printers/jobs/cleanup-orders
5. Drag-Drop-Konfiguration abrufen
GET /api/printers/drag-drop/config
🔐 Berechtigungen
Erforderliche Rechte
- Job-Reihenfolge anzeigen: Alle angemeldeten Benutzer
- Job-Reihenfolge ändern:
Permission.APPROVE_JOBS
erforderlich - Eigene Jobs verschieben: Benutzer können nur ihre eigenen Jobs verschieben
- Alle Jobs verwalten: Administratoren können alle Jobs verschieben
- System-Bereinigung: Nur Administratoren (
Permission.ADMIN
)
Validierung
# Beispiel aus dem Code
if not current_user.is_admin:
user_job_ids = {job.id for job in valid_jobs if job.user_id == current_user.id}
if user_job_ids != set(job_ids):
return jsonify({"error": "Keine Berechtigung für fremde Jobs"}), 403
🚀 Performance-Optimierungen
1. Intelligentes Caching
- Job-Reihenfolgen: Im Speicher-Cache für schnelle Zugriffe
- TTL-basiert: Automatische Cache-Invalidierung nach bestimmter Zeit
- Event-basiert: Cache wird bei Änderungen sofort invalidiert
2. Datenbank-Optimierungen
- Indizierte Abfragen: Foreign Keys sind automatisch indiziert
- Batch-Updates: Mehrere Änderungen in einer Transaktion
- Optimierte Joins: Effiziente Datenbankabfragen für Job-Details
3. Hintergrund-Bereinigung
def _schedule_cleanup(self):
"""Plant eine Bereinigung für später (non-blocking)"""
cleanup_thread = threading.Thread(target=cleanup_worker, daemon=True)
cleanup_thread.start()
🛠️ Verwendung für Entwickler
Frontend-Integration
// Drag-Drop-Konfiguration laden
const response = await fetch('/api/printers/drag-drop/config');
const config = await response.json();
// Job-Reihenfolge aktualisieren
const updateOrder = async (printerId, jobIds) => {
const response = await fetch(`/api/printers/${printerId}/jobs/order`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ job_ids: jobIds })
});
return response.json();
};
Neue Jobs automatisch einordnen
# Beispiel: Neuer Job wird automatisch ans Ende der Reihenfolge gesetzt
def add_new_job_to_order(job):
current_order = drag_drop_manager.get_job_order(job.printer_id)
new_order = current_order + [job.id]
drag_drop_manager.update_job_order(job.printer_id, new_order)
🔧 Migration und Setup
Automatische Datenbank-Migration
Die JobOrder-Tabelle wird automatisch beim Anwendungsstart erstellt:
# In app.py wird setup_database_with_migrations() aufgerufen
def setup_database_with_migrations():
# Erstellt alle Tabellen inklusive JobOrder
Base.metadata.create_all(engine)
# Prüft spezifisch auf JobOrder-Tabelle
if 'job_orders' not in existing_tables:
JobOrder.__table__.create(engine, checkfirst=True)
🐛 Fehlerbehandlung
Typische Fehlerszenarien
- Ungültige Job-IDs: Jobs existieren nicht oder gehören zu anderem Drucker
- Berechtigungsfehler: Benutzer versucht fremde Jobs zu verschieben
- Datenbankfehler: Transaktions-Rollback bei Fehlern
- Cache-Inkonsistenz: Automatische Cache-Bereinigung bei Fehlern
Robuste Error-Recovery
try:
success = JobOrder.update_printer_order(printer_id, job_ids, user_id)
if success:
self.job_order_cache[printer_id] = job_ids
return True
except Exception as e:
logger.error(f"Fehler beim Aktualisieren: {str(e)}")
# Cache bereinigen bei Fehlern
self.job_order_cache.pop(printer_id, None)
return False
📊 Monitoring und Logging
Ausführliche Protokollierung
logger.info(f"Job-Reihenfolge für Drucker {printer.name} aktualisiert")
logger.info(f" Neue Reihenfolge: {job_ids}")
logger.info(f" Benutzer: {current_user.name} (ID: {current_user.id})")
Statistiken
- Anzahl der Drag-Drop-Operationen pro Benutzer
- Häufigste Reihenfolge-Änderungen
- Performance-Metriken für Cache-Hits/Misses
🔄 Maintenance und Wartung
Automatische Bereinigung
- Scheduler-Integration: Regelmäßige Bereinigung ungültiger Einträge
- On-Demand-Cleanup: Manuelle Bereinigung über Admin-API
- Cache-Management: Automatische Cache-Größenkontrolle
Datenbank-Wartung
-- Regelmäßige Bereinigung abgeschlossener Jobs
DELETE FROM job_orders
WHERE job_id IN (
SELECT id FROM jobs
WHERE status IN ('finished', 'aborted', 'cancelled')
);
🚀 Zukünftige Erweiterungen
Geplante Features
- Bulk-Operationen: Mehrere Jobs gleichzeitig verschieben
- Templates: Vordefinierte Job-Reihenfolgen speichern
- Automatische Optimierung: KI-basierte Reihenfolge-Vorschläge
- Grafisches Dashboard: Visuelles Drag-Drop-Interface
- Mobile-Optimierung: Touch-freundliche Drag-Drop-Funktionen
Erweiterbarkeit
# Plugin-System für benutzerdefinierte Sortier-Algorithmen
class CustomSortingPlugin:
def sort_jobs(self, jobs: List[Job]) -> List[Job]:
# Benutzerdefinierte Sortierlogik
return sorted_jobs
🎯 Zusammenfassung
Das Drag & Drop System für Job-Reihenfolge-Verwaltung ist vollständig implementiert und bietet:
✅ Vollständige Persistierung - Alle Änderungen werden in der Datenbank gespeichert
✅ Benutzerfreundliche API - RESTful Endpoints für einfache Frontend-Integration
✅ Robuste Berechtigungen - Sichere Zugriffskontrolle und Validierung
✅ Optimierte Performance - Caching und effiziente Datenbankabfragen
✅ Wartungsfreundlich - Automatische Bereinigung und Monitoring
✅ Erweiterbar - Modularer Aufbau für zukünftige Features
Die Implementierung ist produktionsreif und kann sofort verwendet werden. Alle Funktionen sind getestet und dokumentiert.