Projektarbeit-MYP/backend/docs/DRAG_DROP_IMPLEMENTATION.md
2025-06-01 02:00:30 +02:00

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

  1. Ungültige Job-IDs: Jobs existieren nicht oder gehören zu anderem Drucker
  2. Berechtigungsfehler: Benutzer versucht fremde Jobs zu verschieben
  3. Datenbankfehler: Transaktions-Rollback bei Fehlern
  4. 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

  1. Bulk-Operationen: Mehrere Jobs gleichzeitig verschieben
  2. Templates: Vordefinierte Job-Reihenfolgen speichern
  3. Automatische Optimierung: KI-basierte Reihenfolge-Vorschläge
  4. Grafisches Dashboard: Visuelles Drag-Drop-Interface
  5. 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.