# 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
```sql
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
```python
# 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
```python
# 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
```http
GET /api/printers/{printer_id}/jobs/order
```

**Response:**
```json
{
    "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
```http
POST /api/printers/{printer_id}/jobs/order
Content-Type: application/json

{
    "job_ids": [23, 15, 7]  // Neue Reihenfolge
}
```

**Response:**
```json
{
    "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
```http
GET /api/printers/{printer_id}/jobs/summary
```

**Response:**
```json
{
    "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)
```http
POST /api/printers/jobs/cleanup-orders
```

### 5. Drag-Drop-Konfiguration abrufen
```http
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
```python
# 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
```python
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
```javascript
// 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
```python
# 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:

```python
# 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
```python
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
```python
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
```sql
-- 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
```python
# 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. 